Metadata-Version: 2.1
Name: recipie
Version: 0.0.2
Summary: Python idoms and recipes
Author: Harvey Pham
License: BSD 3-Clause License
        
        Copyright (c) 2023, Harvey Pham
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        
        3. Neither the name of the copyright holder nor the names of its
           contributors may be used to endorse or promote products derived from
           this software without specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        
Project-URL: Homepage, https://github.com/harveypham/recipie
Project-URL: Bug Tracker, https://github.com/harveypham/recipie/issues
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE

# Recipie

Python idoms and recipes

# Submodule

Some recipie modules having the same name with standard libraries are meant
as a drop in replacement for their counter parts. For example:

```
# Replace contextlib by recipie.contextlib

#from contextlib import *
from recipie.contextlib import *

# All standard contextlib and recipie.contextlib extensions are available
```

## contextlib

### commit(func, *args, **kwargs) [0.0.1]

Executes *func* if the code ran to completion without any error:

Example:

```
def save_data(data):
    ...

with commit(save_data, data):
    # other actions
    ...

    # save_data is called if there is no error
```

* Also see ***rollback***

### rollback(func, *args, **kwargs) [0.0.1]

Executes *func* if when encouter error

Example:

```
def undo(data):
    ...

with rollback(undo, data):
    # Other actions
    ...
```

* Also see ***commit

### Buffer
Accumulates data into a buffer to be processed when the buffer is full.

Example:

```
def save_data(data: list[int]):
    ...

with Buffer(1000, save_data) as buffer:
    for i in range(1500):
        buffer.add(i)
        # On 1001th item, called save_data to save previous 1000 items
# When out of context, call save_data on the last 500 items
```

## functools

### @scoped

*"Namespaces are one honking great idea -- let's do more of those!"*


Decorates a function to make it part of another namespace


Examples:

```
def retry():
    ...

# Put no_delay under "retry" so it can only be refered to as retry.no_delay
@scoped(retry)
def no_delay():
    ...
```

### @default_on_error(value, errors) [0.0.1]

Decorates a function to return the specified *value* if *errors* is raised.

*value*: Default value to return on error

*errors*: Error or tuple of errors to check for

Example:

```
@default_on_error(None, KeyError)
def get_from_dict(dict_, key):
    return dict_[key] # Possible KeyError

value = get_from_dict(d, "Test") # Value is None when "Test" is not in d

```

### @skip_on_error(errors) [0.0.1]

Decorates a function to return None if *errors* is raised (equivalent to @default_on_error(None, errors)

### @retry(tries, errors, error_filter, delay_gen, log_error) [0.0.1]

Retries function *tries* times if encounter an error that matches errors and error_filter

*tries*: Number of attempts on the function. Must be at least 2

*errors*: exception or tuple of exception to retry

*error_filter*: function that takes in an error and returns
**True** if it is a retriable error

*delay_gen*: Delay generator that produce an iterator of delay values for
use between attempts. Several predefined delay scheme:

* retry.no_delay (default): No delay between calls (equivalent to retry.const_delay(0)).
* retry.const_delay(5): Delay five seconds every time (Delay values are [5, 5, 5, 5, ...]
* retry.exp_delay(5, 100): Delays values are [5, 10, 20, 40, ... 5 * 2 ^ (n - 1)]

Example:

```
@retry(3, NetworkError) # Retry 3 times on NetworkError)
def get_db_connection():
   ...

conn = get_db_connection() # Automatically retry on network error
```

* Either *errors* or *error_filter* must be specified
