on-rails


Nameon-rails JSON
Version 4.2.0 PyPI version JSON
download
home_pagehttps://github.com/Payadel/on_rails
SummarySimple and powerful Railway Oriented library for python
upload_time2023-05-20 16:15:23
maintainer
docs_urlNone
authorPayadel
requires_python>=3.8,<4.0
licenseGPLV3
keywords railway oriented functional programming error handling
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
  <h1>on_rails</h1>
  <br />
  <a href="#getting-started"><strong>Getting Started ยป</strong></a>
  <br />
  <br />
  <a href="https://github.com/Payadel/on_rails/issues/new?assignees=&labels=scope-bug&template=BUG_REPORT.md&title=bug%3A+">Report a Bug</a>
  ยท
  <a href="https://github.com/Payadel/on_rails/issues/new?assignees=&labels=scope-enhancement&template=FEATURE_REQUEST.md&title=feat%3A+">Request a Feature</a>
  .
  <a href="https://github.com/Payadel/on_rails/issues/new?assignees=&labels=help-wanted&template=SUPPORT_QUESTION.md&title=support%3A+">Ask a Question</a>
</div>

<div align="center">
<br />

[![code with love by Payadel](https://img.shields.io/badge/%3C%2F%3E%20with%20%E2%99%A5%20by-Payadel-ff1414.svg?style=flat-square)](https://github.com/Payadel)

[![Build Status](https://img.shields.io/github/actions/workflow/status/Payadel/on_rails/build.yaml?branch=dev)](https://github.com/Payadel/on_rails/actions/workflows/build.yaml?query=branch%3Adev)
[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](coverage.md)
[![PyPI](https://img.shields.io/pypi/v/on_rails.svg)](https://pypi.org/project/on_rails/)

![GitHub](https://img.shields.io/github/license/Payadel/on_rails)
[![Pull Requests welcome](https://img.shields.io/badge/PRs-welcome-ff69b4.svg?style=flat-square)](https://github.com/Payadel/on_rails/issues?q=is%3Aissue+is%3Aopen)



</div>
<details>
<summary>Table of Contents</summary>

- [About](#about)
    - [Purpose](#Purpose)
    - [Motivation](#Motivation)
    - [What problems are solved?](#what-problems-are-solved)
- [Getting Started](#getting-started)
- [Usage](#usage)
    - [Documentation](#documentation)
- [CHANGELOG](#changelog)
- [Features](#features)
- [Roadmap](#roadmap)
- [Support](#support)
- [FAQ](#faq)
- [Project assistance](#project-assistance)
- [Contributing](#contributing)
- [Authors & contributors](#authors--contributors)
- [Security](#security)
- [License](#license)

</details>

## About

`on_rails` is a **Railway-Oriented** programming library for Python. It is designed to help developers write code that
is both easier to read and more resilient to errors. Railway-Oriented programming is a pattern that is similar to
functional programming, but with a focus on handling errors in a more elegant way.

### Railway Oriented

The Railway Oriented Programming (ROP) pattern separates the pure functional domain logic from the side effects, by
representing them as a **sequence of functions** that return an Either type, representing either a successful `Result`
or an error. This allows for better **composition** and **testing** of functions, as well as improving the code's **
maintainability** and **readability**.

It also facilitates the **handling of errors**, as the error handling logic is separated from the main logic, making it
easier to reason about and handle errors in a consistent and predictable manner. Overall, ROP can lead to more robust
and reliable software systems.

### Error Handling

In functional programming, it is not always appropriate to use traditional `try-except` blocks because they can lead to
code that is difficult to read, understand, and maintain.

`on_rails` supports functional error handling. The goal of this library is to make error handling **more explicit,
composable, and testable**. By using this library, developers can write code that is **more robust, maintainable, and
expressive**.

### Motivation

The motivation behind this library is the desire to write code that is **more reliable, easier to understand, and less
prone to errors**. In many cases, functional programming languages provide built-in abstractions for chaining functions
and handling errors. However, for languages that do not have built-in support, libraries like this can provide a useful
alternative.

### What problems are solved?

Railway Oriented Programming (ROP) solves several common problems in software development, such as:

- **Handling errors:** By using an Either (`Result`) type, ROP makes it easy to represent and handle errors in a
  consistent and predictable manner, avoiding errors being thrown and allowing for error handling logic to be separated
  from the main logic.

- **Composition:** ROP separates the pure functional domain logic from the side effects, such as I/O, by representing
  them as a sequence of functions. This makes it easy to compose and chain functions together, enabling better code
  reuse and maintainability.

- **Readability:** The separation of pure functional domain logic from the side effects makes the code more readable and
  understandable, as it makes it clear what each function does and how they relate to each other.

- **Testing:** The pure functional domain logic can be easily tested, as it does not depend on any external state or
  side effects. This simplifies testing and ensures that the code is correct.

Overall, ROP provides a structured approach to software development that makes it easier to handle errors, compose
functions, and test code, leading to more robust and reliable software systems.

Developers can spend less time debugging and more time writing code that adds value to their organization. Additionally,
by using functional programming concepts, developers can write code that is easier to reason about and understand, which
can lead to faster development cycles and better quality code.

## Getting Started

Use `pip` to install package:

`pip install on_rails --upgrade`

## Usage

### Sample 1

```python
from on_rails import Result, def_result


@def_result()
def get_number() -> Result:
    number = int(input("Enter number: "))
    return Result.ok(number)


get_number()
    .on_success(lambda value: print(f"Number is valid: {value}"))
    .on_fail(lambda prev: print(prev.detail))
```

Within the `get_number` function, the user is prompted to enter an integer number. If the user enters a valid integer,
the number is returned as a successful result using `Result.ok()`, otherwise, an error message is returned as a failed
result.

When the number is **not valid**, that is, it cannot be converted to int, an **exception** is raised. Thanks to
the `def_result` decorator, all exceptions are handled and the error details are saved in the Result detail.

The `get_number()` function is then called and its result is **chained** with two methods: `on_success()`
and `on_fail()`. If the `get_number()` function returns a **successful** result, the lambda function passed
to `on_success()` is executed, which prints the valid number entered by the user. If the `get_number()` function returns
a **failed** result, the lambda function passed to `on_fail()` is executed, which prints the error message.

Sample output for **valid** number:

```text
Enter number: 5
Number is valid: 5
```

Sample output for **invalid** number:

```text
Enter number: a
Title: An exception occurred
Message: invalid literal for int() with base 10: 'a'
Code: 500
Exception: invalid literal for int() with base 10: 'a'
Stack trace: ...
```

### Sample 2:

```python
from on_rails import Result, def_result
from on_rails.ResultDetails.Errors import ValidationError


@def_result()
def divide_numbers(a: int, b: int):
    if b == 0:
        return Result.fail(ValidationError(message="Cannot divide by zero"))
    return Result.ok(a / b)


result = divide_numbers(10, 0)

if result.success:
    print(f"Operation was successful: {result.value}")
else:
    print("Operation failed:")
    if result.detail.is_instance_of(ValidationError):
        print("Ooo! This is a validation error!")
    print(result.detail)

```

For better error management, you can also specify the error type.

You can use [the implemented](https://github.com/Payadel/on_rails/tree/main/on_rails/ResultDetails) error types or
implement your own error type.

### Sample 3: Custom Error Detail

```python
from typing import Optional
from on_rails import Result, def_result, ErrorDetail


class CustomErrorDetail(ErrorDetail):
    custom_field: str = "custom field!"

    def __init__(self, message: Optional[str] = None):
        super().__init__(title="This is my custom detail", message=message)
        self.code = 600  # Custom error code

    def __str__(self):
        error_details = super().__str__()
        error_details += f"Custom Field: {self.custom_field}"
        return error_details


@def_result()
def divide_numbers(a: int, b: int):
    if b == 0:
        return Result.fail(CustomErrorDetail(message="Cannot divide by zero"))
    return Result.ok(a / b)

```

### Sample 4: Retry Operations

```python
from on_rails.ResultDetails.Success import CreatedDetail
from on_rails import Result, def_result
import requests


@def_result()
def create_data(url: str, data: dict[str, str]) -> Result:
    response = requests.post(url, data=data, timeout=2000)
    response.raise_for_status()  # Raise an exception if the status code indicates an error

    detail = CreatedDetail() if response.status_code == 201 else None
    return Result.ok(response.json(), detail)


def fake_operation():
    return Result.ok()


fake_operation().on_success(lambda: create_data(url, data), num_of_try=5)

```

In the example above, if the request goes wrong, an **exception** will be raised. By setting `num_of_try`, you can
specify how many times the operation should be repeated in case of an error.

### Sample 5: Async Decorator

By default, all operations are executed **synchronous**. If you want to be **asynchronous** set `is_async` to true.

```python
from on_rails import def_result


@def_result(is_async=True)
async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

```

> Note: In asymmetric mode, **chain** of functions is not supported.

## CHANGELOG

Please see the [CHANGELOG](https://github.com/Payadel/on_rails/blob/main/CHANGELOG.md) file.

## Features

- **Easy to use:** `on_rails` is designed to be simple and easy to use, with a minimal API and clear documentation.
- **Compatibility with existing code:** `on_rails` can be easily added to existing codes without the need for major
  refactoring. You can use decorator for wrap old functions or write new functions without worrying about
  incompatibilities.
- **Save any details you like:** Thanks to
  the [ResultDetail](https://github.com/Payadel/on_rails/blob/main/on_rails/ResultDetail.py) class, you can store
  various information about the output of the function. Also, by inheriting from this class, you can write new and
  customized classes for your project.
- **Special details for errors:** With
  the [ErrorDetail](https://github.com/Payadel/on_rails/blob/main/on_rails/ResultDetails/ErrorDetail.py) class, you can
  store specific details about errors. For example, this class supports **stack trace** in a built-in way.
- **Support for common details by default:**
  In [this link](https://github.com/Payadel/on_rails/tree/main/on_rails/ResultDetails), you can see the different types
  of details that are supported.

## Roadmap

See the [open issues](https://github.com/Payadel/on_rails/issues) for a list of proposed features (and known issues).

- [Top Feature Requests](https://github.com/Payadel/on_rails/issues?q=label%3Ascope-enhancement+is%3Aopen+sort%3Areactions-%2B1-desc) (
  Add your votes using the ๐Ÿ‘ reaction)
- [Top Bugs](https://github.com/Payadel/on_rails/issues?q=is%3Aissue+is%3Aopen+label%3Ascope-bug+sort%3Areactions-%2B1-desc) (
  Add your votes using the ๐Ÿ‘ reaction)
- [Newest Bugs](https://github.com/Payadel/on_rails/issues?q=is%3Aopen+is%3Aissue+label%3Ascope-bug)

## Support

Reach out to the maintainers at one of the following places:

- [GitHub issues](https://github.com/Payadel/on_rails/issues/new?assignees=&labels=help-wanted&template=SUPPORT_QUESTION.md&title=support%3A+)

## FAQ

#### Do I need rewrite all the functions in a new way?

**not necessarily.** You can add this library and write new functions without changing the previous codes.

Also for old functions, you can use **decorator**. By using decorator, The output of the function is converted
to `Result` format. This way, your code is wrap in a `try-except` block to handle all exceptions.

#### How to manage all function exceptions?

By using decorator, your code is wrap in a `try-except` block and the final output is converted to Result. In this way,
all exceptions are handled.

## Project assistance

If you want to say thank you or/and support active development of `on_rails`:

- Add a [GitHub Star](https://github.com/Payadel/on_rails) to the project.
- Write interesting articles about the project on [Dev.to](https://dev.to/), [Medium](https://medium.com/) or your
  personal blog.

Together, we can make `on_rails` **better**!

## Contributing

First off, thanks for taking the time to contribute! Contributions are what make the free/open-source community such an
amazing place to learn, inspire, and create. Any contributions you make will benefit everybody else and are **greatly
appreciated**.

Please read [our contribution guidelines](https://github.com/Payadel/on_rails/blob/main/docs/CONTRIBUTING.md), and thank
you for being involved!

> Please do not forget that this project uses [conventional commits](https://www.conventionalcommits.org), so please follow the specification in your commit messages. You can see valid types from [this file](https://github.com/Payadel/on_rails/blob/main/.configs/commitlint.config.js).

## Authors & contributors

The original setup of this repository is by [Payadel](https://github.com/Payadel).

For a full list of all authors and contributors,
see [the contributors page](https://github.com/Payadel/on_rails/contributors).

## Security

`on_rails` follows good practices of security, but 100% security cannot be assured. `on_rails` is provided **"as is"**
without any **warranty**.

_For more information and to report security issues, please refer to
our [security documentation](https://github.com/Payadel/on_rails/blob/main/docs/SECURITY.md)._

## License

This project is licensed under the **GPLv3**.

See [LICENSE](https://github.com/Payadel/on_rails/blob/main/LICENSE) for more information.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Payadel/on_rails",
    "name": "on-rails",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "railway oriented,functional programming,error handling",
    "author": "Payadel",
    "author_email": "payadelteam@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/c5/34/adcebd712553669590d774e8bc432eca87f7e0fc2826aabb5746d62dcc3a/on_rails-4.2.0.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n  <h1>on_rails</h1>\n  <br />\n  <a href=\"#getting-started\"><strong>Getting Started \u00bb</strong></a>\n  <br />\n  <br />\n  <a href=\"https://github.com/Payadel/on_rails/issues/new?assignees=&labels=scope-bug&template=BUG_REPORT.md&title=bug%3A+\">Report a Bug</a>\n  \u00b7\n  <a href=\"https://github.com/Payadel/on_rails/issues/new?assignees=&labels=scope-enhancement&template=FEATURE_REQUEST.md&title=feat%3A+\">Request a Feature</a>\n  .\n  <a href=\"https://github.com/Payadel/on_rails/issues/new?assignees=&labels=help-wanted&template=SUPPORT_QUESTION.md&title=support%3A+\">Ask a Question</a>\n</div>\n\n<div align=\"center\">\n<br />\n\n[![code with love by Payadel](https://img.shields.io/badge/%3C%2F%3E%20with%20%E2%99%A5%20by-Payadel-ff1414.svg?style=flat-square)](https://github.com/Payadel)\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/Payadel/on_rails/build.yaml?branch=dev)](https://github.com/Payadel/on_rails/actions/workflows/build.yaml?query=branch%3Adev)\n[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](coverage.md)\n[![PyPI](https://img.shields.io/pypi/v/on_rails.svg)](https://pypi.org/project/on_rails/)\n\n![GitHub](https://img.shields.io/github/license/Payadel/on_rails)\n[![Pull Requests welcome](https://img.shields.io/badge/PRs-welcome-ff69b4.svg?style=flat-square)](https://github.com/Payadel/on_rails/issues?q=is%3Aissue+is%3Aopen)\n\n\n\n</div>\n<details>\n<summary>Table of Contents</summary>\n\n- [About](#about)\n    - [Purpose](#Purpose)\n    - [Motivation](#Motivation)\n    - [What problems are solved?](#what-problems-are-solved)\n- [Getting Started](#getting-started)\n- [Usage](#usage)\n    - [Documentation](#documentation)\n- [CHANGELOG](#changelog)\n- [Features](#features)\n- [Roadmap](#roadmap)\n- [Support](#support)\n- [FAQ](#faq)\n- [Project assistance](#project-assistance)\n- [Contributing](#contributing)\n- [Authors & contributors](#authors--contributors)\n- [Security](#security)\n- [License](#license)\n\n</details>\n\n## About\n\n`on_rails` is a **Railway-Oriented** programming library for Python. It is designed to help developers write code that\nis both easier to read and more resilient to errors. Railway-Oriented programming is a pattern that is similar to\nfunctional programming, but with a focus on handling errors in a more elegant way.\n\n### Railway Oriented\n\nThe Railway Oriented Programming (ROP) pattern separates the pure functional domain logic from the side effects, by\nrepresenting them as a **sequence of functions** that return an Either type, representing either a successful `Result`\nor an error. This allows for better **composition** and **testing** of functions, as well as improving the code's **\nmaintainability** and **readability**.\n\nIt also facilitates the **handling of errors**, as the error handling logic is separated from the main logic, making it\neasier to reason about and handle errors in a consistent and predictable manner. Overall, ROP can lead to more robust\nand reliable software systems.\n\n### Error Handling\n\nIn functional programming, it is not always appropriate to use traditional `try-except` blocks because they can lead to\ncode that is difficult to read, understand, and maintain.\n\n`on_rails` supports functional error handling. The goal of this library is to make error handling **more explicit,\ncomposable, and testable**. By using this library, developers can write code that is **more robust, maintainable, and\nexpressive**.\n\n### Motivation\n\nThe motivation behind this library is the desire to write code that is **more reliable, easier to understand, and less\nprone to errors**. In many cases, functional programming languages provide built-in abstractions for chaining functions\nand handling errors. However, for languages that do not have built-in support, libraries like this can provide a useful\nalternative.\n\n### What problems are solved?\n\nRailway Oriented Programming (ROP) solves several common problems in software development, such as:\n\n- **Handling errors:** By using an Either (`Result`) type, ROP makes it easy to represent and handle errors in a\n  consistent and predictable manner, avoiding errors being thrown and allowing for error handling logic to be separated\n  from the main logic.\n\n- **Composition:** ROP separates the pure functional domain logic from the side effects, such as I/O, by representing\n  them as a sequence of functions. This makes it easy to compose and chain functions together, enabling better code\n  reuse and maintainability.\n\n- **Readability:** The separation of pure functional domain logic from the side effects makes the code more readable and\n  understandable, as it makes it clear what each function does and how they relate to each other.\n\n- **Testing:** The pure functional domain logic can be easily tested, as it does not depend on any external state or\n  side effects. This simplifies testing and ensures that the code is correct.\n\nOverall, ROP provides a structured approach to software development that makes it easier to handle errors, compose\nfunctions, and test code, leading to more robust and reliable software systems.\n\nDevelopers can spend less time debugging and more time writing code that adds value to their organization. Additionally,\nby using functional programming concepts, developers can write code that is easier to reason about and understand, which\ncan lead to faster development cycles and better quality code.\n\n## Getting Started\n\nUse `pip` to install package:\n\n`pip install on_rails --upgrade`\n\n## Usage\n\n### Sample 1\n\n```python\nfrom on_rails import Result, def_result\n\n\n@def_result()\ndef get_number() -> Result:\n    number = int(input(\"Enter number: \"))\n    return Result.ok(number)\n\n\nget_number()\n    .on_success(lambda value: print(f\"Number is valid: {value}\"))\n    .on_fail(lambda prev: print(prev.detail))\n```\n\nWithin the `get_number` function, the user is prompted to enter an integer number. If the user enters a valid integer,\nthe number is returned as a successful result using `Result.ok()`, otherwise, an error message is returned as a failed\nresult.\n\nWhen the number is **not valid**, that is, it cannot be converted to int, an **exception** is raised. Thanks to\nthe `def_result` decorator, all exceptions are handled and the error details are saved in the Result detail.\n\nThe `get_number()` function is then called and its result is **chained** with two methods: `on_success()`\nand `on_fail()`. If the `get_number()` function returns a **successful** result, the lambda function passed\nto `on_success()` is executed, which prints the valid number entered by the user. If the `get_number()` function returns\na **failed** result, the lambda function passed to `on_fail()` is executed, which prints the error message.\n\nSample output for **valid** number:\n\n```text\nEnter number: 5\nNumber is valid: 5\n```\n\nSample output for **invalid** number:\n\n```text\nEnter number: a\nTitle: An exception occurred\nMessage: invalid literal for int() with base 10: 'a'\nCode: 500\nException: invalid literal for int() with base 10: 'a'\nStack trace: ...\n```\n\n### Sample 2:\n\n```python\nfrom on_rails import Result, def_result\nfrom on_rails.ResultDetails.Errors import ValidationError\n\n\n@def_result()\ndef divide_numbers(a: int, b: int):\n    if b == 0:\n        return Result.fail(ValidationError(message=\"Cannot divide by zero\"))\n    return Result.ok(a / b)\n\n\nresult = divide_numbers(10, 0)\n\nif result.success:\n    print(f\"Operation was successful: {result.value}\")\nelse:\n    print(\"Operation failed:\")\n    if result.detail.is_instance_of(ValidationError):\n        print(\"Ooo! This is a validation error!\")\n    print(result.detail)\n\n```\n\nFor better error management, you can also specify the error type.\n\nYou can use [the implemented](https://github.com/Payadel/on_rails/tree/main/on_rails/ResultDetails) error types or\nimplement your own error type.\n\n### Sample 3: Custom Error Detail\n\n```python\nfrom typing import Optional\nfrom on_rails import Result, def_result, ErrorDetail\n\n\nclass CustomErrorDetail(ErrorDetail):\n    custom_field: str = \"custom field!\"\n\n    def __init__(self, message: Optional[str] = None):\n        super().__init__(title=\"This is my custom detail\", message=message)\n        self.code = 600  # Custom error code\n\n    def __str__(self):\n        error_details = super().__str__()\n        error_details += f\"Custom Field: {self.custom_field}\"\n        return error_details\n\n\n@def_result()\ndef divide_numbers(a: int, b: int):\n    if b == 0:\n        return Result.fail(CustomErrorDetail(message=\"Cannot divide by zero\"))\n    return Result.ok(a / b)\n\n```\n\n### Sample 4: Retry Operations\n\n```python\nfrom on_rails.ResultDetails.Success import CreatedDetail\nfrom on_rails import Result, def_result\nimport requests\n\n\n@def_result()\ndef create_data(url: str, data: dict[str, str]) -> Result:\n    response = requests.post(url, data=data, timeout=2000)\n    response.raise_for_status()  # Raise an exception if the status code indicates an error\n\n    detail = CreatedDetail() if response.status_code == 201 else None\n    return Result.ok(response.json(), detail)\n\n\ndef fake_operation():\n    return Result.ok()\n\n\nfake_operation().on_success(lambda: create_data(url, data), num_of_try=5)\n\n```\n\nIn the example above, if the request goes wrong, an **exception** will be raised. By setting `num_of_try`, you can\nspecify how many times the operation should be repeated in case of an error.\n\n### Sample 5: Async Decorator\n\nBy default, all operations are executed **synchronous**. If you want to be **asynchronous** set `is_async` to true.\n\n```python\nfrom on_rails import def_result\n\n\n@def_result(is_async=True)\nasync def fetch(session, url):\n    async with session.get(url) as response:\n        return await response.text()\n\n```\n\n> Note: In asymmetric mode, **chain** of functions is not supported.\n\n## CHANGELOG\n\nPlease see the [CHANGELOG](https://github.com/Payadel/on_rails/blob/main/CHANGELOG.md) file.\n\n## Features\n\n- **Easy to use:** `on_rails` is designed to be simple and easy to use, with a minimal API and clear documentation.\n- **Compatibility with existing code:** `on_rails` can be easily added to existing codes without the need for major\n  refactoring. You can use decorator for wrap old functions or write new functions without worrying about\n  incompatibilities.\n- **Save any details you like:** Thanks to\n  the [ResultDetail](https://github.com/Payadel/on_rails/blob/main/on_rails/ResultDetail.py) class, you can store\n  various information about the output of the function. Also, by inheriting from this class, you can write new and\n  customized classes for your project.\n- **Special details for errors:** With\n  the [ErrorDetail](https://github.com/Payadel/on_rails/blob/main/on_rails/ResultDetails/ErrorDetail.py) class, you can\n  store specific details about errors. For example, this class supports **stack trace** in a built-in way.\n- **Support for common details by default:**\n  In [this link](https://github.com/Payadel/on_rails/tree/main/on_rails/ResultDetails), you can see the different types\n  of details that are supported.\n\n## Roadmap\n\nSee the [open issues](https://github.com/Payadel/on_rails/issues) for a list of proposed features (and known issues).\n\n- [Top Feature Requests](https://github.com/Payadel/on_rails/issues?q=label%3Ascope-enhancement+is%3Aopen+sort%3Areactions-%2B1-desc) (\n  Add your votes using the \ud83d\udc4d reaction)\n- [Top Bugs](https://github.com/Payadel/on_rails/issues?q=is%3Aissue+is%3Aopen+label%3Ascope-bug+sort%3Areactions-%2B1-desc) (\n  Add your votes using the \ud83d\udc4d reaction)\n- [Newest Bugs](https://github.com/Payadel/on_rails/issues?q=is%3Aopen+is%3Aissue+label%3Ascope-bug)\n\n## Support\n\nReach out to the maintainers at one of the following places:\n\n- [GitHub issues](https://github.com/Payadel/on_rails/issues/new?assignees=&labels=help-wanted&template=SUPPORT_QUESTION.md&title=support%3A+)\n\n## FAQ\n\n#### Do I need rewrite all the functions in a new way?\n\n**not necessarily.** You can add this library and write new functions without changing the previous codes.\n\nAlso for old functions, you can use **decorator**. By using decorator, The output of the function is converted\nto `Result` format. This way, your code is wrap in a `try-except` block to handle all exceptions.\n\n#### How to manage all function exceptions?\n\nBy using decorator, your code is wrap in a `try-except` block and the final output is converted to Result. In this way,\nall exceptions are handled.\n\n## Project assistance\n\nIf you want to say thank you or/and support active development of `on_rails`:\n\n- Add a [GitHub Star](https://github.com/Payadel/on_rails) to the project.\n- Write interesting articles about the project on [Dev.to](https://dev.to/), [Medium](https://medium.com/) or your\n  personal blog.\n\nTogether, we can make `on_rails` **better**!\n\n## Contributing\n\nFirst off, thanks for taking the time to contribute! Contributions are what make the free/open-source community such an\namazing place to learn, inspire, and create. Any contributions you make will benefit everybody else and are **greatly\nappreciated**.\n\nPlease read [our contribution guidelines](https://github.com/Payadel/on_rails/blob/main/docs/CONTRIBUTING.md), and thank\nyou for being involved!\n\n> Please do not forget that this project uses [conventional commits](https://www.conventionalcommits.org), so please follow the specification in your commit messages. You can see valid types from [this file](https://github.com/Payadel/on_rails/blob/main/.configs/commitlint.config.js).\n\n## Authors & contributors\n\nThe original setup of this repository is by [Payadel](https://github.com/Payadel).\n\nFor a full list of all authors and contributors,\nsee [the contributors page](https://github.com/Payadel/on_rails/contributors).\n\n## Security\n\n`on_rails` follows good practices of security, but 100% security cannot be assured. `on_rails` is provided **\"as is\"**\nwithout any **warranty**.\n\n_For more information and to report security issues, please refer to\nour [security documentation](https://github.com/Payadel/on_rails/blob/main/docs/SECURITY.md)._\n\n## License\n\nThis project is licensed under the **GPLv3**.\n\nSee [LICENSE](https://github.com/Payadel/on_rails/blob/main/LICENSE) for more information.\n",
    "bugtrack_url": null,
    "license": "GPLV3",
    "summary": "Simple and powerful Railway Oriented library for python",
    "version": "4.2.0",
    "project_urls": {
        "Homepage": "https://github.com/Payadel/on_rails",
        "Repository": "https://github.com/Payadel/on_rails"
    },
    "split_keywords": [
        "railway oriented",
        "functional programming",
        "error handling"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e4055eef52ae88d41f4447a1d463f5b5b341656c5d92e70eaf708e102b4eecd9",
                "md5": "57fdbf7efa34de764caa0af8e50a29ac",
                "sha256": "66e7cb8ba685eb3322ed744cfc9896b6346b951e23c3eace4fd07719dc029bb5"
            },
            "downloads": -1,
            "filename": "on_rails-4.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "57fdbf7efa34de764caa0af8e50a29ac",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 39377,
            "upload_time": "2023-05-20T16:15:22",
            "upload_time_iso_8601": "2023-05-20T16:15:22.048908Z",
            "url": "https://files.pythonhosted.org/packages/e4/05/5eef52ae88d41f4447a1d463f5b5b341656c5d92e70eaf708e102b4eecd9/on_rails-4.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c534adcebd712553669590d774e8bc432eca87f7e0fc2826aabb5746d62dcc3a",
                "md5": "f7fb67569f83258b9404c47391ef6534",
                "sha256": "cc4ce22a2e7df9ef8486f1254612dfd5e5a71169078090498a9cd44dfa450530"
            },
            "downloads": -1,
            "filename": "on_rails-4.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "f7fb67569f83258b9404c47391ef6534",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 35403,
            "upload_time": "2023-05-20T16:15:23",
            "upload_time_iso_8601": "2023-05-20T16:15:23.815590Z",
            "url": "https://files.pythonhosted.org/packages/c5/34/adcebd712553669590d774e8bc432eca87f7e0fc2826aabb5746d62dcc3a/on_rails-4.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-20 16:15:23",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Payadel",
    "github_project": "on_rails",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "on-rails"
}
        
Elapsed time: 0.77159s