trcks


Nametrcks JSON
Version 0.3.7 PyPI version JSON
download
home_pageNone
SummaryType-safe railway-oriented programming (ROP)
upload_time2025-10-25 14:47:25
maintainerChristoph Gietl
docs_urlNone
authorChristoph Gietl
requires_python>=3.9
licenseNone
keywords composition control flow error handling fp functional programming monad object-oriented programming oop pipeline railway-oriented programming result type rop static typing type safety
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # trcks 🚂🐍

`trcks` is a Python library that allows
[railway-oriented programming (ROP)](https://fsharpforfunandprofit.com/rop/)
in two different type-safe programming styles.

## Railway-oriented programming (ROP) styles

The following subsections demonstrate
both styles of railway-oriented programming (ROP)
supported by `trcks`.

### Object-oriented style

The object-oriented style is based on method chaining,
as demonstrated by the `get_subscription_fee_by_email` function
in the following example.

```pycon
>>> from typing import Literal, Union
>>> from trcks import Result
>>> from trcks.oop import Wrapper
>>>
>>> UserDoesNotExist = Literal["User does not exist"]
>>> UserDoesNotHaveASubscription = Literal["User does not have a subscription"]
>>> FailureDescription = Union[UserDoesNotExist, UserDoesNotHaveASubscription]
>>>
>>> def get_user_id(user_email: str) -> Result[UserDoesNotExist, int]:
...     if user_email == "erika.mustermann@domain.org":
...         return "success", 1
...     if user_email == "john_doe@provider.com":
...         return "success", 2
...     return "failure", "User does not exist"
...
>>> def get_subscription_id(
...     user_id: int
... ) -> Result[UserDoesNotHaveASubscription, int]:
...     if user_id == 1:
...         return "success", 42
...     return "failure", "User does not have a subscription"
...
>>> def get_subscription_fee(subscription_id: int) -> float:
...     return subscription_id * 0.1
...
>>> def get_subscription_fee_by_email(
...     user_email: str
... ) -> Result[FailureDescription, float]:
...     return (
...         Wrapper(core=user_email)
...         .map_to_result(get_user_id)
...         .map_success_to_result(get_subscription_id)
...         .map_success(get_subscription_fee)
...         .core
...     )
...
>>> get_subscription_fee_by_email("erika.mustermann@domain.org")
('success', 4.2)
>>> get_subscription_fee_by_email("john_doe@provider.com")
('failure', 'User does not have a subscription')
>>> get_subscription_fee_by_email("jane_doe@provider.com")
('failure', 'User does not exist')

```

#### Notes w.r.t. object-oriented style

1. The generic type `trcks.Result` allows domain errors to become
   part of a function's return type (subject to static type checking).
2. The class `trcks.oop.Wrapper` provides a convenient way to chain
   `trcks.Result`-returning functions and "regular" functions
   (in a type-safe way).

### Functional style

The functional style is based on function composition,
as demonstrated by the `get_subscription_fee_by_email` function
in the following example.

```pycon
>>> from typing import Literal, Union
>>> from trcks import Result
>>> from trcks.fp.composition import Pipeline3, pipe
>>> from trcks.fp.monads import result as r
>>>
>>> UserDoesNotExist = Literal["User does not exist"]
>>> UserDoesNotHaveASubscription = Literal["User does not have a subscription"]
>>> FailureDescription = Union[UserDoesNotExist, UserDoesNotHaveASubscription]
>>>
>>> def get_user_id(user_email: str) -> Result[UserDoesNotExist, int]:
...     if user_email == "erika.mustermann@domain.org":
...         return "success", 1
...     if user_email == "john_doe@provider.com":
...         return "success", 2
...     return "failure", "User does not exist"
...
>>> def get_subscription_id(
...     user_id: int
... ) -> Result[UserDoesNotHaveASubscription, int]:
...     if user_id == 1:
...         return "success", 42
...     return "failure", "User does not have a subscription"
...
>>> def get_subscription_fee(subscription_id: int) -> float:
...     return subscription_id * 0.1
...
>>> def get_subscription_fee_by_email(
...     user_email: str
... ) -> Result[FailureDescription, float]:
...     # Explicitly assigning a type to `pipeline` might
...     # help your static type checker understand that
...     # `pipeline` is a valid argument for `pipe`:
...     pipeline: Pipeline3[
...         str,
...         Result[UserDoesNotExist, int],
...         Result[FailureDescription, int],
...         Result[FailureDescription, float],
...     ] = (
...         user_email,
...         get_user_id,
...         r.map_success_to_result(get_subscription_id),
...         r.map_success(get_subscription_fee),
...     )
...     return pipe(pipeline)
...
>>> get_subscription_fee_by_email("erika.mustermann@domain.org")
('success', 4.2)
>>> get_subscription_fee_by_email("john_doe@provider.com")
('failure', 'User does not have a subscription')
>>> get_subscription_fee_by_email("jane_doe@provider.com")
('failure', 'User does not exist')

```

#### Notes w.r.t. functional style

1. The generic type `trcks.Result` allows domain errors to become
   part of a function's return type (subject to static type checking).
2. The modules `trcks.fp.composition` and `trcks.fp.monads.result`
   provide a convenient way to chain
   `trcks.Result`-returning functions and "regular" functions
   (in a type-safe way).

## Setup

`trcks` is [available on PyPI](https://pypi.org/project/trcks/).
Use your favorite package manager (e.g. `pip`, `poetry` or `uv`) to install it.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "trcks",
    "maintainer": "Christoph Gietl",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "composition, control flow, error handling, fp, functional programming, monad, object-oriented programming, oop, pipeline, railway-oriented programming, result type, rop, static typing, type safety",
    "author": "Christoph Gietl",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/74/84/30138780df8d224cbaeafdec4e8020eab20fa6b3efebcb15693f48a30d16/trcks-0.3.7.tar.gz",
    "platform": null,
    "description": "# trcks \ud83d\ude82\ud83d\udc0d\n\n`trcks` is a Python library that allows\n[railway-oriented programming (ROP)](https://fsharpforfunandprofit.com/rop/)\nin two different type-safe programming styles.\n\n## Railway-oriented programming (ROP) styles\n\nThe following subsections demonstrate\nboth styles of railway-oriented programming (ROP)\nsupported by `trcks`.\n\n### Object-oriented style\n\nThe object-oriented style is based on method chaining,\nas demonstrated by the `get_subscription_fee_by_email` function\nin the following example.\n\n```pycon\n>>> from typing import Literal, Union\n>>> from trcks import Result\n>>> from trcks.oop import Wrapper\n>>>\n>>> UserDoesNotExist = Literal[\"User does not exist\"]\n>>> UserDoesNotHaveASubscription = Literal[\"User does not have a subscription\"]\n>>> FailureDescription = Union[UserDoesNotExist, UserDoesNotHaveASubscription]\n>>>\n>>> def get_user_id(user_email: str) -> Result[UserDoesNotExist, int]:\n...     if user_email == \"erika.mustermann@domain.org\":\n...         return \"success\", 1\n...     if user_email == \"john_doe@provider.com\":\n...         return \"success\", 2\n...     return \"failure\", \"User does not exist\"\n...\n>>> def get_subscription_id(\n...     user_id: int\n... ) -> Result[UserDoesNotHaveASubscription, int]:\n...     if user_id == 1:\n...         return \"success\", 42\n...     return \"failure\", \"User does not have a subscription\"\n...\n>>> def get_subscription_fee(subscription_id: int) -> float:\n...     return subscription_id * 0.1\n...\n>>> def get_subscription_fee_by_email(\n...     user_email: str\n... ) -> Result[FailureDescription, float]:\n...     return (\n...         Wrapper(core=user_email)\n...         .map_to_result(get_user_id)\n...         .map_success_to_result(get_subscription_id)\n...         .map_success(get_subscription_fee)\n...         .core\n...     )\n...\n>>> get_subscription_fee_by_email(\"erika.mustermann@domain.org\")\n('success', 4.2)\n>>> get_subscription_fee_by_email(\"john_doe@provider.com\")\n('failure', 'User does not have a subscription')\n>>> get_subscription_fee_by_email(\"jane_doe@provider.com\")\n('failure', 'User does not exist')\n\n```\n\n#### Notes w.r.t. object-oriented style\n\n1. The generic type `trcks.Result` allows domain errors to become\n   part of a function's return type (subject to static type checking).\n2. The class `trcks.oop.Wrapper` provides a convenient way to chain\n   `trcks.Result`-returning functions and \"regular\" functions\n   (in a type-safe way).\n\n### Functional style\n\nThe functional style is based on function composition,\nas demonstrated by the `get_subscription_fee_by_email` function\nin the following example.\n\n```pycon\n>>> from typing import Literal, Union\n>>> from trcks import Result\n>>> from trcks.fp.composition import Pipeline3, pipe\n>>> from trcks.fp.monads import result as r\n>>>\n>>> UserDoesNotExist = Literal[\"User does not exist\"]\n>>> UserDoesNotHaveASubscription = Literal[\"User does not have a subscription\"]\n>>> FailureDescription = Union[UserDoesNotExist, UserDoesNotHaveASubscription]\n>>>\n>>> def get_user_id(user_email: str) -> Result[UserDoesNotExist, int]:\n...     if user_email == \"erika.mustermann@domain.org\":\n...         return \"success\", 1\n...     if user_email == \"john_doe@provider.com\":\n...         return \"success\", 2\n...     return \"failure\", \"User does not exist\"\n...\n>>> def get_subscription_id(\n...     user_id: int\n... ) -> Result[UserDoesNotHaveASubscription, int]:\n...     if user_id == 1:\n...         return \"success\", 42\n...     return \"failure\", \"User does not have a subscription\"\n...\n>>> def get_subscription_fee(subscription_id: int) -> float:\n...     return subscription_id * 0.1\n...\n>>> def get_subscription_fee_by_email(\n...     user_email: str\n... ) -> Result[FailureDescription, float]:\n...     # Explicitly assigning a type to `pipeline` might\n...     # help your static type checker understand that\n...     # `pipeline` is a valid argument for `pipe`:\n...     pipeline: Pipeline3[\n...         str,\n...         Result[UserDoesNotExist, int],\n...         Result[FailureDescription, int],\n...         Result[FailureDescription, float],\n...     ] = (\n...         user_email,\n...         get_user_id,\n...         r.map_success_to_result(get_subscription_id),\n...         r.map_success(get_subscription_fee),\n...     )\n...     return pipe(pipeline)\n...\n>>> get_subscription_fee_by_email(\"erika.mustermann@domain.org\")\n('success', 4.2)\n>>> get_subscription_fee_by_email(\"john_doe@provider.com\")\n('failure', 'User does not have a subscription')\n>>> get_subscription_fee_by_email(\"jane_doe@provider.com\")\n('failure', 'User does not exist')\n\n```\n\n#### Notes w.r.t. functional style\n\n1. The generic type `trcks.Result` allows domain errors to become\n   part of a function's return type (subject to static type checking).\n2. The modules `trcks.fp.composition` and `trcks.fp.monads.result`\n   provide a convenient way to chain\n   `trcks.Result`-returning functions and \"regular\" functions\n   (in a type-safe way).\n\n## Setup\n\n`trcks` is [available on PyPI](https://pypi.org/project/trcks/).\nUse your favorite package manager (e.g. `pip`, `poetry` or `uv`) to install it.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Type-safe railway-oriented programming (ROP)",
    "version": "0.3.7",
    "project_urls": {
        "Documentation": "https://christophgietl.github.io/trcks/",
        "Issues": "https://github.com/christophgietl/trcks/issues",
        "Repository": "https://github.com/christophgietl/trcks.git"
    },
    "split_keywords": [
        "composition",
        " control flow",
        " error handling",
        " fp",
        " functional programming",
        " monad",
        " object-oriented programming",
        " oop",
        " pipeline",
        " railway-oriented programming",
        " result type",
        " rop",
        " static typing",
        " type safety"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "efc9737f989ce27495335e12e3e4404790396aa88e750a4d1d3cd3c84a271d20",
                "md5": "149b2debf7dfee4ad47bd75a4669ee63",
                "sha256": "e88c79245d5c6c2e711ab2cc1803b7c6fe4c26b7f0b046b0692c83fd611b91cf"
            },
            "downloads": -1,
            "filename": "trcks-0.3.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "149b2debf7dfee4ad47bd75a4669ee63",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 24968,
            "upload_time": "2025-10-25T14:47:24",
            "upload_time_iso_8601": "2025-10-25T14:47:24.897038Z",
            "url": "https://files.pythonhosted.org/packages/ef/c9/737f989ce27495335e12e3e4404790396aa88e750a4d1d3cd3c84a271d20/trcks-0.3.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "748430138780df8d224cbaeafdec4e8020eab20fa6b3efebcb15693f48a30d16",
                "md5": "01e4ce9807ee7a49dfbfad478c2be6cf",
                "sha256": "992189f383dd8280367972a39de2cbf33199788307ef8a174f8b974f7bcc12b3"
            },
            "downloads": -1,
            "filename": "trcks-0.3.7.tar.gz",
            "has_sig": false,
            "md5_digest": "01e4ce9807ee7a49dfbfad478c2be6cf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 24119,
            "upload_time": "2025-10-25T14:47:25",
            "upload_time_iso_8601": "2025-10-25T14:47:25.773896Z",
            "url": "https://files.pythonhosted.org/packages/74/84/30138780df8d224cbaeafdec4e8020eab20fa6b3efebcb15693f48a30d16/trcks-0.3.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-25 14:47:25",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "christophgietl",
    "github_project": "trcks",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "trcks"
}
        
Elapsed time: 1.64728s