-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from alice-biometrics/feature/result_id_by_refe…
…rence_on_handle Feature/result id by reference on handle
- Loading branch information
Showing
3 changed files
with
188 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,24 @@ | ||
meiga 🧙 [![version](https://img.shields.io/github/release/alice-biometrics/meiga/all.svg)](https://github.com/alice-biometrics/meiga/releases) [![ci](https://github.com/alice-biometrics/meiga/workflows/ci/badge.svg)](https://github.com/alice-biometrics/meiga/actions) [![pypi](https://img.shields.io/pypi/dm/meiga)](https://pypi.org/project/meiga/) | ||
===== | ||
# meiga 🧙 [![version](https://img.shields.io/github/release/alice-biometrics/meiga/all.svg)](https://github.com/alice-biometrics/meiga/releases) [![ci](https://github.com/alice-biometrics/meiga/workflows/ci/badge.svg)](https://github.com/alice-biometrics/meiga/actions) [![pypi](https://img.shields.io/pypi/dm/meiga)](https://pypi.org/project/meiga/) | ||
|
||
<img src="https://github.com/alice-biometrics/custom-emojis/blob/master/images/alice_header.png" width=auto> | ||
|
||
A simple, typed and monad-based Result type for Python. | ||
|
||
**meiga 🧙** give us a simpler and clearer way of handling errors in Python. Use it whenever a class method or a function has the possibility of failure. | ||
## Table of Contents | ||
- [Installation :computer:](#installation-computer) | ||
- [Getting Started :chart_with_upwards_trend:](#getting-started-chart_with_upwards_trend) | ||
* [Example](#example) | ||
* [Features](#features) | ||
- [Result](#result) | ||
- [Functions](#functions) | ||
- [Properties](#properties) | ||
- [Alias](#alias) | ||
- [Advance Usage :rocket:](#advance-usage-rocket) | ||
* [Unwrap Result](#unwrap-result) | ||
* [Handle Result](#handle-result) | ||
* [Test Assertions](#test-assertions) | ||
- [Contact :mailbox_with_mail:](#contact-mailbox_with_mail) | ||
|
||
This package provides a new type for your Python applications, the **Result[Type, Type]**. | ||
This Result type allows to simplify a wide range of problems, like handling potential undefined values, or reduce complexity handling exceptions. Additionally, code can be simplified following a semantic pipeline reducing the visual noise of checking data types, controlling runtime flow and side-effects. | ||
|
||
This package is based in another solutions from another modern languages as the swift-based [Result](https://github.com/antitypical/Result) implementation. | ||
|
||
## Installation :computer: | ||
|
||
|
@@ -18,9 +28,16 @@ pip install meiga | |
|
||
## Getting Started :chart_with_upwards_trend: | ||
|
||
The best way to illustrate how **meiga 🧙** can help you is with an example. | ||
**Meiga** give us a simpler and clearer way of handling errors in Python. Use it whenever a class method or a function has the possibility of failure. | ||
|
||
This package provides a new type for your Python applications, the **Result[Type, Type]**. | ||
This Result type allows to simplify a wide range of problems, like handling potential undefined values, or reduce complexity handling exceptions. Additionally, code can be simplified following a semantic pipeline reducing the visual noise of checking data types, controlling runtime flow and side-effects. | ||
|
||
This package is based in another solutions from another modern languages as the swift-based [Result](https://github.com/antitypical/Result) implementation. | ||
|
||
### Example | ||
|
||
The best way to illustrate how **meiga 🧙** can help you is with an example. | ||
|
||
Consider the following example of a function that tries to extract a String (str) for a given key from a Dict. | ||
|
||
|
@@ -50,11 +67,11 @@ def string_from_key(dictionary: dict, key: str) -> Result[str, Error]: | |
Result meiga type provides a robust wrapper around the functions. | ||
Rather than throw an exception, it returns a Result that either contains the String value for the given key, or an ErrorClass detailing what went wrong. | ||
|
||
## Features | ||
### Features | ||
|
||
#### Result[T, Error] | ||
#### Result | ||
|
||
A discriminated union that encapsulates successful outcome with a value of type T or a failure with an arbitrary Error exception. | ||
`Result[T, Error]` 👉 A discriminated union that encapsulates successful outcome with a value of type T or a failure with an arbitrary Error exception. | ||
|
||
#### Functions | ||
|
||
|
@@ -131,7 +148,7 @@ True | |
TypeMismatch() // Error | ||
``` | ||
|
||
### Alias | ||
#### Alias | ||
|
||
Use meiga aliases to improve the semantics of your code. | ||
|
||
|
@@ -216,6 +233,8 @@ class AuthService: | |
return NotImplementedMethodError | ||
``` | ||
|
||
## Advance Usage :rocket: | ||
|
||
### Unwrap Result | ||
|
||
If you *wrap* a Result object, its will return a valid value if it is success. Otherwise, it will return None. | ||
|
@@ -231,9 +250,32 @@ value = result.unwrap() | |
assert value is None | ||
``` | ||
|
||
* Check [Functions](#functions) to know more about *unwraping* methods. | ||
* Check [tests/unit/test_result_unwrap.py](https://github.com/alice-biometrics/meiga/blob/master/tests/unit/test_result_unwrap.py) to see examples of usage. | ||
|
||
|
||
You can use `unwrap_or_return`in combination with `@meiga` decorator. If something wrong happens unwraping your `Result`, the `unwrap_or_return` function will raise an Exception (ReturnErrorOnFailure). `@meiga` decorator allows to handle the exception in case of error and unwrap the value in case of success. The following example illustrate this: | ||
|
||
```python | ||
from meiga import Result, Error | ||
from meiga.decorators import meiga | ||
|
||
@meiga | ||
def handling_result(key: str) -> Result: | ||
user_info = {"first_name": "Rosalia", "last_name": "De Castro", "age": 60} | ||
first_name = string_from_key(dictionary=user_info, key=key).handle() | ||
# Do whatever with the name | ||
name = first_name.lower() | ||
return Result(success=name) | ||
``` | ||
|
||
If key is valid success value would be returned. Otherwise, an Error would be returned. | ||
|
||
|
||
### Handle Result | ||
|
||
This framework also allows a method for handling Result type | ||
This framework also allows a method for handling Result type. `handle` method returns itself and execute the `on_success` function when the instance represemts success and the `on_failure` function when it is failure. | ||
|
||
|
||
When the operations is executed with its happy path, handle function returns the success value, as with result.value. | ||
|
||
|
@@ -259,6 +301,8 @@ result = string_from_key(dictionary=user_info, key="first_name") | |
result.handle(on_success=success_handler, on_failure=failure_handler) | ||
``` | ||
|
||
##### Additional parameters | ||
|
||
If you need to add some arguments as a parameters, use **success_args** and **failure_args**: | ||
|
||
```python | ||
|
@@ -278,29 +322,46 @@ result.handle(on_success=success_handler, | |
failure_args=(1, 2)) | ||
``` | ||
|
||
##### Additional parameters in combination with the Result itself | ||
|
||
On the other hand, if something wrong happens handle function will raise an Exception (ReturnErrorOnFailure). | ||
Meiga has available a decorator to allow to handle the exception in case of error and unwrap the value in case of success. | ||
|
||
Sometimes a handle function will need information about external parameters and also about the result itself. Now, is possible this combination thanks to `Result.__id__` identifier. | ||
|
||
```python | ||
from meiga import Result, Error | ||
from meiga.decorators import meiga | ||
|
||
@meiga | ||
def handling_result(key: str) -> Result: | ||
user_info = {"first_name": "Rosalia", "last_name": "De Castro", "age": 60} | ||
first_name = string_from_key(dictionary=user_info, key=key).handle() | ||
# Do whatever with the name | ||
name = first_name.lower() | ||
return Result(success=name) | ||
parameters = (1, Result.__id__, 2) | ||
|
||
def on_success(param_1: int, result: Result, param_2: int): | ||
assert param_1 == 1 | ||
assert isinstance(result, Result) | ||
assert result.value is True | ||
assert param_2 == 2 | ||
|
||
def on_failure(param_1: int, result: Result, param_2: int): | ||
assert param_1 == 1 | ||
assert isinstance(result, Result) | ||
assert result.value == Error() | ||
assert param_2 == 2 | ||
|
||
@meiga | ||
def run(): | ||
result.handle( | ||
on_success=on_success, | ||
on_failure=on_failure, | ||
success_args=parameters, | ||
failure_args=parameters, | ||
) | ||
|
||
run() | ||
``` | ||
|
||
If key is valid success value would be returned. Otherwise, an Error would be returned. | ||
|
||
|
||
### Assertions | ||
|
||
### Test Assertions | ||
|
||
To help us on testing functions that returns Result, meiga provide us two functions: **assert_success** and **access_failure**. | ||
|
||
Check the following pytest-based test for more information: [tests/unit/test_result_assertions.py](https://github.com/alice-biometrics/meiga/blob/master/tests/unit/test_result_assertions.py) | ||
|
||
## Contact :mailbox_with_mail: | ||
|
||
[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters