Skip to main content

Python library to user type guard utilities to check parameters and return type, allow function overloading and function mocking at runtime

Project description

DecoratorUtilities

Readthedocs Reference

Please read our documentation here: Readthedocs Reference

Package Reference

Our package reference link is: https://pypi.org/project/decoratorutilities

Menu

Intro

DecoratorUtilities is a python library that provides different utilities for functions and class methods such as to check parameters and return type, allow overloading, to cache results to speed up them, instantiate a Singleton object and mocking at runtime

Installation

pip install decoratorutilities

Decorators

Check Type Decorator

Decorate your own functions with @checktype decorator to check parameters type and return type too Example:

from decoratorutilities import checktype
import pytest

@checktype
def my_functon(a: int, b: int) -> int:
    return 1

# Valid usage: Integer parameters and return type
my_functon(5, 6)  # return 1
assert my_functon(5, 6) == 1  # True

# Invalid usage: String parameters and return type
with pytest.raises(TypeError):
    my_functon("5", "6")  # Raises TypeError Exception
with pytest.raises(TypeError):
    my_functon("invalid", b="Invalid")  # Raises TypeError Exception
with pytest.raises(TypeError):
    my_functon(a="invalid", b="Invalid")  # Raises TypeError Exception
with pytest.raises(TypeError):
    assert my_functon(5, 6) == "1"  # Raises TypeError Exception

Decorate your own class methods with @checktype decorator to check parameters type and return type too Example:

from decoratorutilities import checktype
import pytest

class X(object):

    @checktype  # checktype decorator for classes methods
    def my_function(self, value: int):
        return value

# Valid usage: Integer parameters and return type
assert X().my_function(1) == 1  # True

# Invalid usage: String parameters and return type
with pytest.raises(TypeError):
    X().my_function('1')  # Raises TypeError Exception
with pytest.raises(TypeError):
    X().my_function(1) == "1"  # Raises TypeError Exception

Overloading Decorator

Decorate your own function with @overload decorator to define multiple functions with same name but with different parameters
Example:

from decoratorutilities import overload

@overload
def my_functon(a:int):
    return 1

@overload
def my_functon(a:str):
    return 2

# Invoke first my_functon and return 1
my_functon(1)
# Invoke second my_functon and return 2
my_functon('1')

Decorate your own class method with @overload decorator to define multiple class methods with same name but with different parameters
Example:

from decoratorutilities import overload

class X(object):
    @overload
    def x(self, x: int):
        return int

    @overload
    def x(self, x: str):
        return str

assert X().x(1) == int  # True
assert X().x('1') == str  # True

Mocking Decorator

Decorate your own function with @mocking decorator to mock that function adding args in a tuple, kwargs in a dict and return value
Example:

from decoratorutilities import mocking

# Define args tuple, kwargs dict and return value
@mocking([
   ((1, 2, 3), {"a": 1}, 1),
   ((4, 5, 6), {"b": 2}, 2)
])
def a():
   pass

# Valid usage
assert a(1, 2, 3, a=1) == 1  # return 1
assert a(4, 5, 6, b=2) == 2  # return 2

# Invalid usage
assert a(7, 8, 9, c=1) == 1  # Raises KeyError Exception

Memoized Decorator

Decorate your own function or class method with @memoized decorator to speed up it by storing the results and returning the cached result when the same inputs occur again
Example:

from decoratorutilities import memoized
import datetime

def util_run_function_with_time(fn, args, kwargs):
    start_time = datetime.datetime.now()
    tmp = fn(*args, **kwargs)
    end_time = datetime.datetime.now()
    return (end_time - start_time), tmp

@memoized
def memoized_fibonacci(x):
    if x == 0:
        return 0

    if x == 1:
        return 1

    return memoized_fibonacci(x - 1) + memoized_fibonacci(x - 2)

def fibonacci(x):
    if x == 0:
        return 0

    if x == 1:
        return 1

    return fibonacci(x - 1) + fibonacci(x - 2)

fib_value = 20
memoized_execution_time, memoized_value = util_run_function_with_time(memoized_fibonacci, (fib_value, ), {})  # Return execution time and value for memoized function
unmemoized_execution_time, unmemoized_value = util_run_function_with_time(fibonacci, (fib_value, ), {})  # Return execution time and value for unmemoized function

print(f"memoized_execution_time: {memoized_execution_time} - unmemoized_execution_time: {unmemoized_execution_time}")

assert memoized_execution_time < unmemoized_execution_time  # OK
assert memoized_value == unmemoized_value  # OK

Timeit Decorator

Decorate your own function with @timeit decorator to monitoring execution time
Example:

from decoratorutilities import timeit
import time


@timeit
def hello():
    time.sleep(0.1)


if __name__ == "__main__":
    hello()  # print "Execution time: 100.75 ms"

Debug Decorator

Decorate your own function with @debug decorator to print in console more Exception details
Example:

from decoratorutilities import debug
import pytest

@debug
def a():
    message = "Hello " + 5
    return message

with pytest.raises(TypeError):
    a() # Print in console: Found "<class 'TypeError'>" Exception in file "('../tests', 'test_debug.py')" on line "9"
        # Error message: "can only concatenate str (not "int") to str"

Decorate your own class methods with @debug decorator to print in console more Exception details
Example:

from decoratorutilities import debug
import pytest

class A(object):

    @debug
    def __init__(self):
        self.message = "Hello " + 5

with pytest.raises(TypeError):
    A()  # Raises TypeError Exception

Singleton Decorator

Decorate your own classes with @singleton() decorator to ensure that only one instance of the singleton class ever exists. Never invoke @singleton() decorator without brackets otherwise it will cause problems Define your class method __init__() without parameters, pass them to the @singleton() decorator

Example with args and kwargs

import pytest
from decoratorutilities import singleton

@singleton(10, message="Message to send", email=["simone.scalamandre95@gmail.com"])
class A(object):
    def __init__(self):
        self.x = 50  # Define constant class attribute

    def print_hello(self):  # Custom method
        return "Hello World"

# Valid usage
assert A[0] == 10  # True -> Get first arg
assert A.x == 50  # True -> Get decorated class attribute
assert A.print_hello() == "Hello World"  # True -> Get decorated class method "print_hello()"
assert A.message == "Message to send"  # True -> Get kwarg "message" passed to Singleton decorator
assert A.email == ["simone.scalamandre95@gmail.com"]  # True

with pytest.raises(TypeError):
    # Invalid usage, brackets are missing
    @singleton
    class B(object):
        def __init__(self):
            self.x = 10

    B()  # Raises TypeError Exception

We can define our singleton class with or without args and kwargs parameters but we can only instantiate one Example

import pytest
from decoratorutilities import singleton

@singleton()
class A(object):
    def __init__(self):
        pass

@singleton(x=10)
class B(object):
    def __init__(self):
        pass

with pytest.raises(TypeError) as e:
    A()  # Raises TypeError Exception

with pytest.raises(TypeError):
    B()  # Raises TypeError Exception

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

decoratorutilities-1.0.2.tar.gz (9.7 kB view hashes)

Uploaded Source

Built Distribution

decoratorutilities-1.0.2-py3-none-any.whl (13.3 kB view hashes)

Uploaded Python 3

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