Skip to main content

Decorator which checks whether the function is called with the correct type of parameters

Project description

Strong Typing

Decorator which checks at Runtime whether the function is called with the correct type of parameters.
And raises TypeMisMatch if the used parameters in a function call where invalid.

The problem:

def multipler(a: int, b: int):
    return a * b


product = multipler(3, 4)
# >>> 12

# Some IDE's will/can highlight that one of the parameter doesn't match but you can run it
product_2 = multipler('Hello', 'World')
# >>> TypeError
# When we receiver an Exception then we are ‘safe’ and know what to do 
# but sometimes we will not run into an Exception

product_3 = multipler('Hello', 4)
# >>> 'HelloHelloHelloHello'
# No Exception but the result isn’t really what we expect

Now we can say that we will check the types in the function body to prevent this.


def multipler(a: int, b: int):
    if isinstance(a, int) and isinstance(b, int):
        return a * b
    ...

But when your function needs a lot of different parameters with different types you have to create a lot of noising code.
And why should we then use typing in our parameters??

My solution:

I created a decorator called @match_typing which will check at runtime if the parameters you used when calling this function are from the same type as you wanted.

Here are some examples from my tests
@match_typing
def func_a(a: str, b: int, c: list):
    ...

func_a('1', 2, [i for i in range(5)])
# >>> True

func_a(1, 2, [i for i in range(5)])
# >>> will raise a TypeMismatch Exception

@match_typing
def func_e(a: List[Union[str, int]], b: List[Union[str, int, tuple]]):
    return f'{len(a)}-{len(b)}'

func_e([1, '2', 3, '4'], [5, ('a', 'b'), '10'])
# >>> '4-3'

func_e([5, ('a', 'b'), '10'], [1, '2', 3, datetime.date])
# >>> will raise a TypeMismatch Exception

I really love python and his freedom but with the new option of adding type hints I wanted to get rid of writing if isinstance(value, whatever) in my programs.

In a bigger project it happened that some developers used a really tiny IDE and others a more advanced one which highlighted typing issues. And there the trouble began, we had a bug and after a longer debugging session we found out that the issue was a wrong type of an argument, it doesn't crashed the program but the output was totally not what we expected.

And this is the reason why I created this package.

Getting Started

As normal decorator

from strongtyping.strong_typing import match_typing

@match_typing
def foo_bar(a: str, b: int, c: list):
    ...

as class method decorator

from strongtyping.strong_typing import match_typing

class Foo:
    ...
    @match_typing
    def foo_bar(self, a: int):
        ...

You can also use a mix of typed and untyped parameters but then only the typed parameters are checked on runtime

from strongtyping.strong_typing import match_typing

@match_typing
def foo_bar(with_type_a: str, without_type_a, with_type_b: list, without_type_b):
    ...

# no exception
foo_bar('hello', 'world', [1, 2, 3], ('a', 'b'))

# will raise an exception
foo_bar(123, 'world', [1, 2, 3], ('a', 'b'))

It is also possibile to add you own exception

from strongtyping.strong_typing import match_typing

class SomeException(Exception):
    pass

@match_typing(excep_raise=SomeException)
def foo_bar(with_type_a: str, without_type_a, with_type_b: list, without_type_b):
    ...

And last but not least you can also enable internal cache with cache_size = 1

from strongtyping.strong_typing import match_typing

class MyClass:
    pass

@match_typing(cache_size=1)
def foo_bar(a: tuple, b: MyClass):
    ...

You can also disable the raise of an Exception and get a warning instead
this means your function will execute even when the parameters are wrong
use only when you know what you're doing

from strongtyping.strong_typing import match_typing

@match_typing(excep_raise=None)
def multipler(a: int, b: int):
    return a * b

print(multipler('Hello', 4))
"""
/StrongTyping/strongtyping/strong_typing.py:208: RuntimeWarning: Incorrect parameters: a: <class 'int'>
  warnings.warn(msg, RuntimeWarning)
HelloHelloHelloHello
"""

At the current state it will work with

  • builtin types like: str, int, tuple etc
  • from typing:
    • List
    • Tuple
    • Union also nested ( Tuple[Union[str, int], Union[list, tuple]] )
    • Any
    • Dict
    • Set
    • Type
    • Iterator
    • Callable
    • Generator
  • from types:
    • FunctionType
    • MethodType
  • with string types representation like
from strongtyping.strong_typing import match_typing

class A:
    @match_typing
    def func_a(self, a: 'A'):
        ...

Now with support for reST docstrings

therefore use the decorator match_docstring

from strongtyping.docstring_typing import match_docstring

@match_docstring
def func_a(a):
    """
    :param a:
    :type a: list
    ...
    """

@match_docstring
def func_a(a, b):
    """
    :param int a: foo
    :vartype b: str
    ...
    """

@match_docstring
def func_a(a, b):
    """
    :parameter int a: foo
    :argument str b: bar
    ...
    """

At the current state it will work with basically everything which is written here https://gist.github.com/jesuGMZ/d83b5e9de7ccc16f71c02adf7d2f3f44

  • extended with support for
    • Iterator
    • Callable
    • Generator
    • FunctionType
    • MethodType

please check tests/test_typing to see what is supported

Tested for Versions

  • 3.6, 3.7, 3.8

Installing

Versioning

  • For the versions available, see the tags on this repository.

Authors

  • Felix Eisenmenger - Initial work

License

  • This project is licensed under the MIT License - see the LICENSE.md file for details

Special thanks

  • Thanks to Ruud van der Ham for helping me improve my code
  • And all how gave me Feedback in the Pythonista Cafe

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

strongtyping-1.3.1.tar.gz (14.5 kB view details)

Uploaded Source

Built Distribution

strongtyping-1.3.1-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file strongtyping-1.3.1.tar.gz.

File metadata

  • Download URL: strongtyping-1.3.1.tar.gz
  • Upload date:
  • Size: 14.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.8.3

File hashes

Hashes for strongtyping-1.3.1.tar.gz
Algorithm Hash digest
SHA256 92786e5721e6a2cc9a6076d43f2c722e8730abf6f7307adaa1220878a6ac85b5
MD5 fa2a39f6060bdf3b903b98c377a00ad8
BLAKE2b-256 989018a698e6017bbda485864e5287ec0d264e01b8472d2d7878878e8d77587b

See more details on using hashes here.

File details

Details for the file strongtyping-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: strongtyping-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.8.3

File hashes

Hashes for strongtyping-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 86e9e4fbba281dfd088bdd62cd3aad42e670dd849aaee04df6c6fc73ac19ad06
MD5 ee072512aedb5c078dc2d5041f92bceb
BLAKE2b-256 d5afee2d4f75e95fc77a44c4e6440a4b5486d558fb655bfa05359a1dcd7af447

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