Skip to main content

A lib to help you avoid spaghetti code

Project description

Py-Macaroni

This is a library to help you avoid Spaghetti Code. It helps you express your application logic in a testable way. The whole idea for this lib was based on some concepts from functional programming and rust, mainly the "unwrap" concept from rust.

Why

When creating bussiness logic for your application, sometimes it gets hard to structure complex logic in a easy to understand way. To help with that, this library was created. The main objective is to help you structure your application in a clean and readable way, enabling future maintenance of the code.

For example, if you have a CRUD application, some logic will be shared between the Create and Update functions, the lib, in this case, can help by chaining functions required to implement the main bussiness rule, and makes it easier to reuse functions when required.

import macaroni as mci

class BussinessLogic(mci.Macaroni):
    def validate_request(self, data):
        # ...

    def check_user_permissions(self, data):
        # ...

    def log_operation(self, data):
        # ...

    def create_item(self, data):
        # ...

    def update_item(self, data):
        # ...

    @mci.error
    def handle_error(self, data, error):
        # ...

    @mci.exception(DuplicateKey)
    def handle_duplicate_item(self, data, exception):
        # ...


def create_item(data):
    bl = BussinessLogic(data)
    result = (
        bl.validate_request()
        .check_user_permissions()
        .create_item()
        .log_operation()
        .handle_error()
        .handle_duplicate_item()
        .unwrap()
    )
    return result


def update_item(data):
    bl = BussinessLogic(data)
    result = (
        bl.validate_request()
        .check_user_permissions()
        .update_item()
        .log_operation()
        .handle_error()
        .unwrap()
    )
    return result

It also helps you avoid dealing with error and exception handling on each part of your application logic, letting you handle then only at the end of the application execution, automatically skipping steps in your application logic when an error or exception happens.

Installation

pip install macaroni

Usage

More examples can be found in the ./examples directory.

import macaroni as mci

class Calculator(mci.Macaroni):
    def increment(self, value, increment=None):
        if increment is None:
            increment = 1

        return value + increment

    def divide(self, value, denominator):
        if denominator == 0:
            return mci.Error('invalid denominator {0}'.format(denominator))

        return value / denominator

    def invalid(self, value):
        raise ValueError('invalid data')


base_val = 10
calc = Calcultator(base_val)
result = calc \
    .increment(2) \
    .divide(2) \
    .unwrap() # this returns the final result
assert result == 6

Error handling:

calc = Calculator(10)
result = calc \
    .increment(2) # this is executed \
    .divide(-3) # this causes an error \
    .increment() # this is not executed \
    .unwrap() # returns the error

assert bool(calc.error) == True
assert result == 'invalid denominator 0'

Exception handling:

calc = Calculator(10)
try:
    calc \
        .increment(2) # this is executed \
        .invalid() # this causes an exception \
        .increment() # this is not executed \
        .unwrap() # the exception ValueError is raised on unwrap
except ValueError:
    pass

assert bool(calc.exception) == True

When testing, you can use the parameter magic=False to disable the automatic value passing, chaining and error/exception handling:

def test_increment():
    calc = Calculator(magic=False)
    result = calc.increment(10, 2)
    assert result == 12

def test_error():
    calc = Calculator(magic=False)
    result = calc.divide(10, 0)
    assert calc.error is not None
    assert result = 'invalid denominator 0'

def test_exception()
    calc = Calculator(magic=False)

    raised_error = False
    try:
        calc.invalid(10)
    except ValueError:
        raised_error = True

    assert raised_error

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

macaroni-0.0.3.tar.gz (4.2 kB view details)

Uploaded Source

Built Distribution

macaroni-0.0.3-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file macaroni-0.0.3.tar.gz.

File metadata

  • Download URL: macaroni-0.0.3.tar.gz
  • Upload date:
  • Size: 4.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.3

File hashes

Hashes for macaroni-0.0.3.tar.gz
Algorithm Hash digest
SHA256 31442aff1a1a5acccea23647d29dac63acf8efea5a2109879156c65ac79b043a
MD5 e50f3b3ebc6ed03e575d57314ceef67d
BLAKE2b-256 4346661ebe62baba8ba286cea1c2fe66fca86158beca48623804ff01ed7e1d8b

See more details on using hashes here.

File details

Details for the file macaroni-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: macaroni-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 5.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.3

File hashes

Hashes for macaroni-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e6f45b42e62cef03adf67ca7091ba68f8734025590f7ddd09daf66a06b7344ed
MD5 d78135fce2b10c0aac9e1df5f4b44324
BLAKE2b-256 7b6b1a427720633cf48c28d1c94aaae4f5873db11ebd913b259cc8c81e89b4ef

See more details on using hashes here.

Supported by

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