Skip to main content

Tiny IO/Try-like effect wrapper for Python.

Project description

PyIO - Python Effects System

A lightweight monadic effects system for Python that provides safe error handling and functional composition. PyIO wraps values and exceptions, allowing you to chain operations without explicit error checking at each step.

Overview

PyIO acts like a Try type - it can hold either a successful value or a captured exception. Operations are automatically skipped if a previous step failed, and errors propagate through the chain until handled.

Core Concept

from pyio import PyIO

# Success case
result = PyIO("hello").map(str.upper).get()  # "HELLO"

# Error case - division by zero is captured and propagated
result = PyIO(10).map(lambda x: x // 0).get_or_else(42)  # 42

Operators

Transformation Operators

  • map(func) - Transform the value if successful, capture any exceptions thrown by func
  • flat_map(func) - Transform with a function that returns a PyIO, flatten the result
  • filter(predicate) - Keep value only if predicate returns True, otherwise become empty

Recovery Operators

  • recover(func) - Handle errors by providing a recovery function that takes the exception
  • recover_with(func) - Handle errors with a function that returns a PyIO

Conditional Operators

  • when(predicate, func) - Apply func only if predicate returns True

Parallel Processing Operators

  • on_parallel(func_1, func_2, merge_func, max_workers=None) - Run two functions concurrently on the same value, then merge their results using merge_func

Side-Effect Operators

  • on_success(func) - Execute a side-effect function if the PyIO contains a value
  • on_error(func) - Execute a side-effect function if the PyIO contains an error

State Inspection Operators

  • is_success() - Returns True if the PyIO contains a value and no error
  • is_error() - Returns True if the PyIO contains an error
  • is_empty() - Returns True if the PyIO's value is None

Extraction Operators

  • get() - Extract the value (unsafe - throws if there was an error)
  • get_or_else(default) - Extract the value or return default if error/None
  • failed() - Extract the captured exception (returns the BaseException)

Usage Examples

Basic Chaining

result = (PyIO("hello world")
          .map(str.upper)
          .map(lambda s: s + "!!!")
          .get())  # "HELLO WORLD!!!"

Error Handling

result = (PyIO(10)
          .map(lambda x: x // 0)  # ZeroDivisionError captured
          .recover(lambda ex: 999)  # Recover with default value
          .map(lambda x: x * 2)
          .get())  # 1998

Conditional Processing

result = (PyIO(15)
          .when(lambda n: n > 10, lambda n: n * 100)
          .get())  # 1500

Parallel Processing

import time

def slow_double(x):
    time.sleep(1)
    return x * 2

def slow_square(x):
    time.sleep(1)
    return x ** 2

result = (PyIO(5)
          .on_parallel(
              slow_double,    # 5 * 2 = 10
              slow_square,    # 5 ** 2 = 25
              lambda a, b: a + b,  # 10 + 25 = 35
              max_workers=2
          )
          .get())  # 35 (computed in ~1 second instead of 2)

State Inspection

# Check if computation was successful
pyio_value = PyIO(42).map(lambda x: x * 2)
if pyio_value.is_success():
    print(f"Success: {pyio_value.get()}")

# Check for errors
pyio_error = PyIO(10).map(lambda x: x // 0)
if pyio_error.is_error():
    print(f"Error occurred: {pyio_error.failed()}")

# Check if value is None
empty_pyio = PyIO(None)
if empty_pyio.is_empty():
    print("Value is None")

Side Effects

result = (PyIO("processing data")
          .on_success(lambda msg: print(f"LOG: {msg}"))  # Prints log message
          .map(str.upper)
          .on_success(lambda msg: print(f"RESULT: {msg}"))  # Prints result
          .get())

Error Side Effects

result = (PyIO(10)
          .map(lambda x: x // 0)  # This will fail
          .on_error(lambda ex: print(f"Error logged: {type(ex).__name__}"))
          .recover(lambda ex: 0)
          .get())  # 0

Installation

Simply copy the pyio.py file to your project directory and import:

from pyio import PyIO

License

This project is open source. See the license file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyio_effect-0.1.4.tar.gz (5.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyio_effect-0.1.4-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file pyio_effect-0.1.4.tar.gz.

File metadata

  • Download URL: pyio_effect-0.1.4.tar.gz
  • Upload date:
  • Size: 5.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for pyio_effect-0.1.4.tar.gz
Algorithm Hash digest
SHA256 3f1886fda94b790b9bd41b208ab22e466194783e1d996bde3ca734e541ef292d
MD5 4543b552e4d4370182778e3c8e7e772a
BLAKE2b-256 eb25dd6c091cd917ceda2d02538d1e106da183cfd0d105e614db2bc0e80149a4

See more details on using hashes here.

File details

Details for the file pyio_effect-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: pyio_effect-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 5.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for pyio_effect-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 46931e44d796d9948cd39e6ed6475b3f11a43e47d2c24a0211e5aacaa496c111
MD5 41a27a937cd1ee3207922f6cfcf849aa
BLAKE2b-256 b4d50562d9201c44fd6a7436e687d814f36320f64b8ca255df6540f4998d2c78

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page