Design-by-contract in Python3 with informative violation messages and inheritance

Overview

icontract

Continuous integration https://coveralls.io/repos/github/Parquery/icontract/badge.svg?branch=master PyPI - version

PyPI - Python Version

Documentation Gitter chat

icontract provides design-by-contract to Python3 with informative violation messages and inheritance.

It also gives a base for a flourishing of a wider ecosystem:

Related Projects

There exist a couple of contract libraries. However, at the time of this writing (September 2018), they all required the programmer either to learn a new syntax (PyContracts) or to write redundant condition descriptions ( e.g., contracts, covenant, deal, dpcontracts, pyadbc and pcd).

This library was strongly inspired by them, but we go two steps further.

First, our violation message on contract breach are much more informative. The message includes the source code of the contract condition as well as variable values at the time of the breach. This promotes don't-repeat-yourself principle (DRY) and spare the programmer the tedious task of repeating the message that was already written in code.

Second, icontract allows inheritance of the contracts and supports weakining of the preconditions as well as strengthening of the postconditions and invariants. Notably, weakining and strengthening of the contracts is a feature indispensable for modeling many non-trivial class hierarchies. Please see Section Inheritance. To the best of our knowledge, there is currently no other Python library that supports inheritance of the contracts in a correct way.

In the long run, we hope that design-by-contract will be adopted and integrated in the language. Consider this library a work-around till that happens. You might be also interested in the archived discussion on how to bring design-by-contract into Python language on python-ideas mailing list.

Teasers

We give a couple of teasers here to motivate the library. Please see the documentation available on icontract.readthedocs.io for a full scope of its capabilities.

The script is also available as a repl.it post.

None: ... pass ... >>> some_func(x=1) Traceback (most recent call last): ... icontract.errors.ViolationError: File , line 1 in : x must not be small: x > 3: x was 1 y was 5 # Pre-condition violation with more complex values >>> class B: ... def __init__(self) -> None: ... self.x = 7 ... ... def y(self) -> int: ... return 2 ... ... def __repr__(self) -> str: ... return "instance of B" ... >>> class A: ... def __init__(self) -> None: ... self.b = B() ... ... def __repr__(self) -> str: ... return "instance of A" ... >>> SOME_GLOBAL_VAR = 13 >>> @icontract.require(lambda a: a.b.x + a.b.y() > SOME_GLOBAL_VAR) ... def some_func(a: A) -> None: ... pass ... >>> an_a = A() >>> some_func(an_a) Traceback (most recent call last): ... icontract.errors.ViolationError: File , line 1 in : a.b.x + a.b.y() > SOME_GLOBAL_VAR: SOME_GLOBAL_VAR was 13 a was instance of A a.b was instance of B a.b.x was 7 a.b.y() was 2 # Post-condition >>> @icontract.ensure(lambda result, x: result > x) ... def some_func(x: int, y: int = 5) -> int: ... return x - y ... >>> some_func(x=10) Traceback (most recent call last): ... icontract.errors.ViolationError: File , line 1 in : result > x: result was 5 x was 10 y was 5 # Pre-conditions fail before post-conditions. >>> @icontract.ensure(lambda result, x: result > x) ... @icontract.require(lambda x: x > 3, "x must not be small") ... def some_func(x: int, y: int = 5) -> int: ... return x - y ... >>> some_func(x=3) Traceback (most recent call last): ... icontract.errors.ViolationError: File , line 2 in : x must not be small: x > 3: x was 3 y was 5 # Invariant >>> @icontract.invariant(lambda self: self.x > 0) ... class SomeClass: ... def __init__(self) -> None: ... self.x = -1 ... ... def __repr__(self) -> str: ... return "an instance of SomeClass" ... >>> some_instance = SomeClass() Traceback (most recent call last): ... icontract.errors.ViolationError: File , line 1 in : self.x > 0: self was an instance of SomeClass self.x was -1">
>>> import icontract

>>> @icontract.require(lambda x: x > 3)
... def some_func(x: int, y: int = 5) -> None:
...     pass
...

>>> some_func(x=5)

# Pre-condition violation
>>> some_func(x=1)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[1]>, line 1 in <module>:
x > 3:
x was 1
y was 5

# Pre-condition violation with a description
>>> @icontract.require(lambda x: x > 3, "x must not be small")
... def some_func(x: int, y: int = 5) -> None:
...     pass
...
>>> some_func(x=1)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[4]>, line 1 in <module>:
x must not be small: x > 3:
x was 1
y was 5

# Pre-condition violation with more complex values
>>> class B:
...     def __init__(self) -> None:
...         self.x = 7
...
...     def y(self) -> int:
...         return 2
...
...     def __repr__(self) -> str:
...         return "instance of B"
...
>>> class A:
...     def __init__(self) -> None:
...         self.b = B()
...
...     def __repr__(self) -> str:
...         return "instance of A"
...
>>> SOME_GLOBAL_VAR = 13
>>> @icontract.require(lambda a: a.b.x + a.b.y() > SOME_GLOBAL_VAR)
... def some_func(a: A) -> None:
...     pass
...
>>> an_a = A()
>>> some_func(an_a)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[9]>, line 1 in <module>:
a.b.x + a.b.y() > SOME_GLOBAL_VAR:
SOME_GLOBAL_VAR was 13
a was instance of A
a.b was instance of B
a.b.x was 7
a.b.y() was 2

# Post-condition
>>> @icontract.ensure(lambda result, x: result > x)
... def some_func(x: int, y: int = 5) -> int:
...     return x - y
...
>>> some_func(x=10)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[12]>, line 1 in <module>:
result > x:
result was 5
x was 10
y was 5


# Pre-conditions fail before post-conditions.
>>> @icontract.ensure(lambda result, x: result > x)
... @icontract.require(lambda x: x > 3, "x must not be small")
... def some_func(x: int, y: int = 5) -> int:
...    return x - y
...
>>> some_func(x=3)
Traceback (most recent call last):
  ...
icontract.errors.ViolationError: File <doctest README.rst[14]>, line 2 in <module>:
x must not be small: x > 3:
x was 3
y was 5

# Invariant
>>> @icontract.invariant(lambda self: self.x > 0)
... class SomeClass:
...     def __init__(self) -> None:
...         self.x = -1
...
...     def __repr__(self) -> str:
...         return "an instance of SomeClass"
...
>>> some_instance = SomeClass()
Traceback (most recent call last):
 ...
icontract.errors.ViolationError: File <doctest README.rst[16]>, line 1 in <module>:
self.x > 0:
self was an instance of SomeClass
self.x was -1

Installation

  • Install icontract with pip:
pip3 install icontract

Versioning

We follow Semantic Versioning. The version X.Y.Z indicates:

  • X is the major version (backward-incompatible),
  • Y is the minor version (backward-compatible), and
  • Z is the patch version (backward-compatible bug fix).
Comments
  • "Soft" contracts

    This is a proposal to introduce new functionality, "soft contracts".

    Problem

    Sometimes you want to track unwanted behaviour but instead of getting an exception, you want to log it.

    Say, your code is already in production and nothing fatal happens when this unwanted behaviour occurs. You want to track and eliminate it, but if you use the usual contracts, the users would suffer - the execution will stop at the contract point with an exception. Thus trying to catch a minor unwanted behaviour via introducing a contract would cause a bigger problem.

    So, you insert logging code into the body of your function. But now the code is less readable because of the "service code injections". The code would be cleaner if you used decorators similar to what icontract provides.

    Proposal

    Introduce a set of decorators named require_soft, ensure_soft, invariant_soft that would log an error (or a warning?) in case the condition is breached, but keep on running.

    This way the users are not harmed and the developer can track the bugs through inspecting the logs.

    opened by leshchenko1979 16
  • require decorator removes type annotations for mypy

    require decorator removes type annotations for mypy

    $ cat ic.py  
    from icontract import require
    
    @require(lambda x: x > 0)
    def f1(x: int): return x
    
    def f2(x: int): return 0
    
    f1("this is wrong")
    f2("this is too")
    
    $ mypy ic.py              
    ic.py:9: error: Argument 1 to "f2" has incompatible type "str"; expected "int"
    

    Both function calls are invalid types but mypy only sees the call as f2 as wrong. The decorator loses the type annotations?

    Related https://github.com/python/mypy/issues/3157

    opened by jamescasbon 12
  • AttributeError in contract caused by method call in constructor

    AttributeError in contract caused by method call in constructor

    When a method is called in the constructor, an AttributeError is raised in the contract. Here is a reproducer:

    from icontract import invariant
    
    
    @invariant(lambda self: all(" " not in part for part in self.parts))
    class ID:
        def __init__(self, identifier: str) -> None:
            self.parts = identifier.split(self.separator())
    
        def separator(self) -> str:
            return "."
    
    
    ID("A")
    
    $ python test.py  
    Traceback (most recent call last):
      File "test.py", line 14, in <module>
        ID("A")
      File "/home/tr/.local/lib/python3.8/site-packages/icontract/_checkers.py", line 461, in wrapper
        result = func(*args, **kwargs)
      File "test.py", line 7, in __init__
        self.parts = identifier.split(self.separator)
      File "/home/tr/.local/lib/python3.8/site-packages/icontract/_checkers.py", line 498, in wrapper
        _assert_invariant(contract=contract, instance=instance)
      File "/home/tr/.local/lib/python3.8/site-packages/icontract/_checkers.py", line 162, in _assert_invariant
        check = contract.condition(self=instance)
      File "test.py", line 4, in <lambda>
        @invariant(lambda self: all(" " not in part for part in self.parts))
    AttributeError: 'ID' object has no attribute 'parts'
    

    The contract works correctly when self.separator() is replaced by a string literal.

    Versions

    icontract 2.3.4 asttokens 2.0.4 Python 3.8.5

    opened by treiher 11
  • *args and **kwargs not supported

    *args and **kwargs not supported

    Given the following code snippet:

    from icontract import require
    
    
    def test_args():
        @require(lambda *args: args)
        def args(*args, **kwargs):
            pass
        args(0, x=0)
    
    
    def test_kwargs():
        @require(lambda **kwargs: kwargs)
        def args(*args, **kwargs):
            pass
        args(0, x=0)
    
    
    def test_both():
        @require(lambda *args, **kwargs: args and kwargs)
        def args(*args, **kwargs):
            pass
        args(0, x=0)
    

    I get errors saying that precondition arguments could not be set (from _checkers.py:114).

    Unless I've missed it, the README didn't explicitly state that * and ** aren't supported. My use case is a rather generic decorator applied to some endpoints. It shouldn't matter how these endpoints are called, but they must contain a request (for the decorator to do its magic), for which I want to create a contract.

    Some observations:

    • @require(lambda args: ...) without the asterisk only passes the first argument supplied to the function to the check (i.e. 0, not [0])
    • @require(lambda kwargs: ...) without the asterisks raises the same error

    I would gladly help with fixing/implementing this since I believe every language today should provide tools for DBC, and your library does a good job. Any thoughts on the feasibility of this? :)

    opened by ghost 11
  • Transpiler

    Transpiler

    (From python-ideas list in thread: "old" values in postconditions)

    What about a tool that converts contracts back and forth to readable form on IDE save/load with the following syntax:

    with contracts:
        with preconditions:
            assert arg1 < arg2
    
        with snapshot as S:
            S.var1 = some_func(arg1)
            with postconditions, \
                 resultie as result:
                     # result would be annotated with "# type:" 
                     # if return type is annotated.
                     assert arg1 < S.var1 < arg2, \
                         "Some contract description"
                      
                     # if not (...) followed by a raise statement 
                     # allows for custom exceptions
                     if not (arg1 > arg2):
                         "another contract description"
                         raise SomeException("some message", arg1)
                     
                     # if (..) followed by a list of asserts or if-not-raises 
                     # allows for toggling contracts
                     if some_enabled_flag:
                         assert arg1 + 10 < arg2
                         assert arg2 > 0
                         if not some_func(arg1, arg2):
                             raise AnotherException("some message", var1, arg1, arg2)
    

    For classes:

    class SomeClass:
        with invariants,
            selfie as self: # type: SomeClass
                 assert 0 < self.x < sqrt(self.x)
    

    icontract.dummies would provide these dummy context managers (all of them would raise exceptions on enter so that the code can not run by accident). The converter would add/remove these imports automatically.

    The advantage: no variable shadowing, valid python code, autocomplete works in Pycharm, even mypy could be made to work. with contracts makes it easier and less error prone to group preconditions and postconditions. The converter would check that there is no "with contracts" in the body of the function except in the first statement (and the same for class invariants).

    Descriptions in asserts and if-not-raise must be string literals (without format() etc.).

    wontfix 
    opened by mristin 11
  • Invariant on a class changes the type of the class

    Invariant on a class changes the type of the class

    from icontract import invariant
    
    class TestClass1():
        test_int: int = 1
    
    reveal_type(TestClass1)
    # Type[TestClass1]
    
    @invariant(lambda self: self.test_int == 1)
    class TestClass2():
        test_int: int = 1
    
    reveal_type(TestClass2)
    # type
    
    opened by ciresnave 10
  • convert readme example into a script that can be easily copy/pasted

    convert readme example into a script that can be easily copy/pasted

    this might just be my personal preference but i feel that it's easy to run and work with the example this way. direct copy and paste into a script would allow you to run the example and step through each piece without losing information. i also added an example showing that "Pre-conditions fail before Post-conditions". that wasn't immediately obvious to me. of course the big assumption is that people would know how to handle the python debugger. i'd guess that more people are familiar with the terminal session. so perhaps this won't be accepted. but with some simple instructions, literally just, type "c" and press enter, you'll walk through each example while being able to inspect either the result or the exception that was raised for each scenario. enjoying testing out the library, thanks :-)

    opened by wgwz 10
  • fixed performance regression due to state

    fixed performance regression due to state

    This commit makes a couple of fixes to improve the computational efficiency of the contracts. There was a performance regression when the state was introduced (notably, ExitStack caused a lot of overhead).

    This commit also introduces benchmarking into the continuous integration (as part of the precommit.py script) so that we can continously monitor the efficiency in the future.

    Fixes #142 .

    opened by mristin 10
  • Failed to recompute the values of the contract condition

    Failed to recompute the values of the contract condition

    I have the following code:

    @ensure(
        lambda result: len(result) > 30_000, "Too few lines"
    )
    @ensure(
        lambda result: all(
            result[col].notna().sum() / len(result) > 0.3 for col in FILTER_FEATURES
        ),
        "Filter features are not filled in properly",
    )
    def load_listings(regions=None) -> pd.DataFrame:
    ...
    

    If the first contract fails, I'm getting a RuntimeError instead of a ViolationError:

    Traceback (most recent call last):
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 2070, in wsgi_app
        response = self.full_dispatch_request()
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1515, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1513, in full_dispatch_request
        rv = self.dispatch_request()
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1499, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
      File "/workspace/main.py", line 43, in main
        listings = load_listings()
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/icontract/_checkers.py", line 646, in wrapper
        violation_error = _assert_postconditions(
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/icontract/_checkers.py", line 396, in _assert_postconditions
        exception = _create_violation_error(contract=contract, resolved_kwargs=resolved_kwargs)
      File "/layers/google.python.pip/pip/lib/python3.9/site-packages/icontract/_checkers.py", line 192, in _create_violation_error
        raise RuntimeError(''.join(parts)) from err
    RuntimeError: Failed to recompute the values of the contract condition:
    File /workspace/main.py, line 65 in <module>:
    Too few lines: lambda result: len(result) > 30_000
    

    I also made the second one fail with pytest, and the test output was:

    ./test_minos.py::test_loading Failed: [undefined]RuntimeError: Failed to recompute the values of the contract condition:
    File c:\Users\leshc\flipio\minos\main.py, line 68 in <module>:
    Filter features are not filled in properly: lambda result: all(
            result[col].notna().sum() / len(result) > 0.3 for col in FILTER_FEATURES
        )
    contract = <icontract._types.Contract object at 0x000001C5B46DACA0>
    resolved_kwargs = {'_ARGS': (), '_KWARGS': {}, 'regions': None, 'result':        repair  house_material  windows_type  room_type
    0      ...         NaN           NaN        NaN
    39999     NaN             NaN           NaN        NaN
    
    [40000 rows x 4 columns]}
    
        def _create_violation_error(contract: Contract, resolved_kwargs: Mapping[str, Any]) -> BaseException:
            """Create the violation error based on the violated contract."""
            exception = None  # type: Optional[BaseException]
        
            if contract.error is None:
                try:
    >               msg = icontract._represent.generate_message(contract=contract, resolved_kwargs=resolved_kwargs)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_checkers.py:181: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    contract = <icontract._types.Contract object at 0x000001C5B46DACA0>
    resolved_kwargs = {'_ARGS': (), '_KWARGS': {}, 'regions': None, 'result':        repair  house_material  windows_type  room_type
    0      ...         NaN           NaN        NaN
    39999     NaN             NaN           NaN        NaN
    
    [40000 rows x 4 columns]}
    
        def generate_message(contract: Contract, resolved_kwargs: Mapping[str, Any]) -> str:
            """Generate the message upon contract violation."""
            parts = []  # type: List[str]
        
            if contract.location is not None:
                parts.append("{}:\n".format(contract.location))
        
            if contract.description is not None:
                parts.append("{}: ".format(contract.description))
        
            lambda_inspection = None  # type: Optional[ConditionLambdaInspection]
            if not is_lambda(a_function=contract.condition):
                condition_text = contract.condition.__name__
            else:
                # We need to extract the source code corresponding to the decorator since inspect.getsource() is broken with
                # lambdas.
                lambda_inspection = inspect_lambda_condition(condition=contract.condition)
                assert lambda_inspection is not None, \
                    "Unexpected no lambda inspection for condition: {}".format(contract.condition)
                condition_text = lambda_inspection.text
        
            parts.append(condition_text)
        
    >       repr_vals = repr_values(
                condition=contract.condition,
                lambda_inspection=lambda_inspection,
                resolved_kwargs=resolved_kwargs,
                a_repr=contract._a_repr)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_represent.py:542: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    condition = <function <lambda> at 0x000001C5B46E48B0>
    lambda_inspection = <icontract._represent.ConditionLambdaInspection object at 0x000001C5B484EF40>
    resolved_kwargs = {'_ARGS': (), '_KWARGS': {}, 'regions': None, 'result':        repair  house_material  windows_type  room_type
    0      ...         NaN           NaN        NaN
    39999     NaN             NaN           NaN        NaN
    
    [40000 rows x 4 columns]}
    a_repr = <reprlib.Repr object at 0x000001C5A34D9BB0>
    
        def repr_values(condition: Callable[..., bool], lambda_inspection: Optional[ConditionLambdaInspection],
                        resolved_kwargs: Mapping[str, Any], a_repr: reprlib.Repr) -> List[str]:
            """
            Represent function arguments and frame values in the error message on contract breach.
        
            :param condition: condition function of the contract
            :param lambda_inspection:
                inspected lambda AST node corresponding to the condition function (None if the condition was not given as a
                lambda function)
            :param resolved_kwargs: arguments put in the function call
            :param a_repr: representation instance that defines how the values are represented.
            :return: list of value representations
            """
            # Hide _ARGS and _KWARGS if they are not part of the condition for better readability
            if '_ARGS' in resolved_kwargs or '_KWARGS' in resolved_kwargs:
                parameters = inspect.signature(condition).parameters
                malleable_kwargs = cast(
                    MutableMapping[str, Any],
                    resolved_kwargs.copy()  # type: ignore
                )
        
                if '_ARGS' not in parameters:
                    malleable_kwargs.pop('_ARGS', None)
        
                if '_KWARGS' not in parameters:
                    malleable_kwargs.pop('_KWARGS', None)
        
                selected_kwargs = cast(Mapping[str, Any], malleable_kwargs)
            else:
                selected_kwargs = resolved_kwargs
        
            # Don't use ``resolved_kwargs`` from this point on.
            # ``selected_kwargs`` is meant to be used instead for better readability of error messages.
        
            if is_lambda(a_function=condition):
                assert lambda_inspection is not None, "Expected a lambda inspection when given a condition as a lambda function"
            else:
                assert lambda_inspection is None, "Expected no lambda inspection in a condition given as a non-lambda function"
        
            reprs = None  # type: Optional[MutableMapping[str, Any]]
        
            if lambda_inspection is not None:
                variable_lookup = collect_variable_lookup(condition=condition, resolved_kwargs=selected_kwargs)
        
                recompute_visitor = icontract._recompute.Visitor(variable_lookup=variable_lookup)
        
    >           recompute_visitor.visit(node=lambda_inspection.node.body)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_represent.py:463: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Call object at 0x000001C5B486ABB0>
    
        def visit(self, node):
            """Visit a node."""
            method = 'visit_' + node.__class__.__name__
            visitor = getattr(self, method, self.generic_visit)
    >       return visitor(node)
    
    C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\ast.py:407: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Call object at 0x000001C5B486ABB0>
    
        def visit_Call(self, node: ast.Call) -> Any:
            """Visit the function and the arguments and finally make the function call with them."""
            func = self.visit(node=node.func)
        
            # Please see "NOTE ABOUT PLACEHOLDERS AND RE-COMPUTATION"
            if func == PLACEHOLDER:
                return PLACEHOLDER
        
            if not callable(func):
                raise ValueError("Unexpected call to a non-calllable during the re-computation: {}".format(func))
        
            if inspect.iscoroutinefunction(func):
                raise ValueError(
                    ("Unexpected coroutine function {} as a condition of a contract. "
                     "You must specify your own error if the condition of your contract is a coroutine function."
                     ).format(func))
        
            # Short-circuit tracing the all quantifier over a generator expression
            # yapf: disable
            if (
                    func == builtins.all  # pylint: disable=comparison-with-callable
                    and len(node.args) == 1
                    and isinstance(node.args[0], ast.GeneratorExp)
            ):
                # yapf: enable
    >           result = self._trace_all_with_generator(func=func, node=node)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:567: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    func = <built-in function all>, node = <ast.Call object at 0x000001C5B486ABB0>
    
        def _trace_all_with_generator(self, func: Callable[..., Any], node: ast.Call) -> Any:
            """Re-write the all call with for loops to trace the first offending item, if any."""
            assert func == builtins.all  # pylint: disable=comparison-with-callable
            assert len(node.args) == 1
            assert isinstance(node.args[0], ast.GeneratorExp)
        
            # Try the happy path first
        
            # Please see "NOTE ABOUT PLACEHOLDERS AND RE-COMPUTATION"
    >       recomputed_arg = self.visit(node=node.args[0])
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:733: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.GeneratorExp object at 0x000001C5B486AAC0>
    
        def visit(self, node):
            """Visit a node."""
            method = 'visit_' + node.__class__.__name__
            visitor = getattr(self, method, self.generic_visit)
    >       return visitor(node)
    
    C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\ast.py:407: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.GeneratorExp object at 0x000001C5B486AAC0>
    
        def visit_GeneratorExp(self, node: ast.GeneratorExp) -> Any:
            """Compile the generator expression as a function and call it."""
            # NOTE ABOUT PLACEHOLDERS AND RE-COMPUTATION:
            # Re-computing the comprehensions would be too slow. Therefore we re-compile the comprehension and call
            # the compiled code directly.
            #
            # However, we still want to report the values of the variables unrelated to the comprehension back
            # to the user. Therefore we introduce PLACEHOLDER's and propagate them through re-computation in all
            # the visit methods.
        
            # The following visits propagate the visitation to descendant nodes.
            # However, as we re-compute the comprehension *via* re-compilation & execution,
            # the results of the visits are all PLACEHOLDER's.
        
            # NOTE ABOUT NAME #x1F812 VALUE STACKING:
            # We need to make a copy of name #x1F812 value mapping since we need to add targets as placeholders
            # while we visit the comprehension. For example, as we compute comprehensions through re-compilation
            # and not through manual re-computation, we can not re-compute nested comprehensions.
            #
            # However, when our visit of comprehension is finished, the targets are not valid any more,
            # so we need to remove them from the mapping.
            #
            # Finally, we compute the comprehension with the original name #x1F812 value mapping by using
            # re-compilation. This final step is skipped if any of the names involved in the comprehension are
            # PLACEHOLDER's.
        
            old_name_to_value = copy.copy(self._name_to_value)
            for target_name in _collect_stored_names([generator.target for generator in node.generators]):
                self._name_to_value[target_name] = PLACEHOLDER
        
    >       self.visit(node.elt)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:846: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Compare object at 0x000001C5B486AB20>
    
        def visit(self, node):
            """Visit a node."""
            method = 'visit_' + node.__class__.__name__
            visitor = getattr(self, method, self.generic_visit)
    >       return visitor(node)
    
    C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\ast.py:407: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Compare object at 0x000001C5B486AB20>
    
        def visit_Compare(self, node: ast.Compare) -> Any:
            """Recursively visit the comparators and apply the operations on them."""
    >       left = self.visit(node=node.left)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:499: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.BinOp object at 0x000001C5B486AA00>
    
        def visit(self, node):
            """Visit a node."""
            method = 'visit_' + node.__class__.__name__
            visitor = getattr(self, method, self.generic_visit)
    >       return visitor(node)
    
    C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\ast.py:407: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.BinOp object at 0x000001C5B486AA00>
    
        def visit_BinOp(self, node: ast.BinOp) -> Any:
            """Recursively visit the left and right operand, respectively, and apply the operation on the results."""
            left = self.visit(node=node.left)
    >       right = self.visit(node=node.right)
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:441: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Call object at 0x000001C5B486A8B0>
    
        def visit(self, node):
            """Visit a node."""
            method = 'visit_' + node.__class__.__name__
            visitor = getattr(self, method, self.generic_visit)
    >       return visitor(node)
    
    C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\ast.py:407: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <icontract._recompute.Visitor object at 0x000001C5B48575E0>
    node = <ast.Call object at 0x000001C5B486A8B0>
    
        def visit_Call(self, node: ast.Call) -> Any:
            """Visit the function and the arguments and finally make the function call with them."""
            func = self.visit(node=node.func)
        
            # Please see "NOTE ABOUT PLACEHOLDERS AND RE-COMPUTATION"
            if func == PLACEHOLDER:
                return PLACEHOLDER
        
            if not callable(func):
                raise ValueError("Unexpected call to a non-calllable during the re-computation: {}".format(func))
        
            if inspect.iscoroutinefunction(func):
                raise ValueError(
                    ("Unexpected coroutine function {} as a condition of a contract. "
                     "You must specify your own error if the condition of your contract is a coroutine function."
                     ).format(func))
        
            # Short-circuit tracing the all quantifier over a generator expression
            # yapf: disable
            if (
                    func == builtins.all  # pylint: disable=comparison-with-callable
                    and len(node.args) == 1
                    and isinstance(node.args[0], ast.GeneratorExp)
            ):
                # yapf: enable
                result = self._trace_all_with_generator(func=func, node=node)
        
                if result is PLACEHOLDER:
                    return PLACEHOLDER
            else:
                args = []  # type: List[Any]
                for arg_node in node.args:
                    if isinstance(arg_node, ast.Starred):
                        args.extend(self.visit(node=arg_node))
                    else:
                        args.append(self.visit(node=arg_node))
        
                kwargs = dict()  # type: Dict[Union[str, Placeholder], Any]
                for keyword in node.keywords:
                    if keyword.arg is None:
                        kw = self.visit(node=keyword.value)
                        for key, val in kw.items():
                            kwargs[key] = val
        
                    else:
                        kwargs[keyword.arg] = self.visit(node=keyword.value)
        
                # Please see "NOTE ABOUT PLACEHOLDERS AND RE-COMPUTATION"
    >           if PLACEHOLDER in args or PLACEHOLDER in kwargs or PLACEHOLDER in kwargs.values():
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_recompute.py:590: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self =        repair  house_material  windows_type  room_type
    0       False           False         False      False
    1       ...        False         False      False
    39999   False           False         False      False
    
    [40000 rows x 4 columns]
    
        @final
        def __nonzero__(self):
    >       raise ValueError(
                f"The truth value of a {type(self).__name__} is ambiguous. "
                "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
            )
    E       ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\generic.py:1537: ValueError
    
    The above exception was the direct cause of the following exception:
    
    monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x000001C5B46EC0D0>
    
        def test_loading(monkeypatch):
            def fake_load_psql(*args, **kwargs):
                return pd.DataFrame([{} for _ in range(40_000)], columns=FILTER_FEATURES)
        
            monkeypatch.setattr(main, "load_psql", fake_load_psql)
    >       load_listings()
    
    test_minos.py:22: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_checkers.py:646: in wrapper
        violation_error = _assert_postconditions(
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_checkers.py:396: in _assert_postconditions
        exception = _create_violation_error(contract=contract, resolved_kwargs=resolved_kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    contract = <icontract._types.Contract object at 0x000001C5B46DACA0>
    resolved_kwargs = {'_ARGS': (), '_KWARGS': {}, 'regions': None, 'result':        repair  house_material  windows_type  room_type
    0      ...         NaN           NaN        NaN
    39999     NaN             NaN           NaN        NaN
    
    [40000 rows x 4 columns]}
    
        def _create_violation_error(contract: Contract, resolved_kwargs: Mapping[str, Any]) -> BaseException:
            """Create the violation error based on the violated contract."""
            exception = None  # type: Optional[BaseException]
        
            if contract.error is None:
                try:
                    msg = icontract._represent.generate_message(contract=contract, resolved_kwargs=resolved_kwargs)
                except Exception as err:
                    parts = ["Failed to recompute the values of the contract condition:\n"]
                    if contract.location is not None:
                        parts.append("{}:\n".format(contract.location))
        
                    if contract.description is not None:
                        parts.append("{}: ".format(contract.description))
        
                    parts.append(icontract._represent.represent_condition(condition=contract.condition))
        
    >               raise RuntimeError(''.join(parts)) from err
    E               RuntimeError: Failed to recompute the values of the contract condition:
    E               File c:\Users\leshc\flipio\minos\main.py, line 68 in <module>:
    E               Filter features are not filled in properly: lambda result: all(
    E                       result[col].notna().sum() / len(result) > 0.3 for col in FILTER_FEATURES
    E                   )
    
    ..\..\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\icontract\_checkers.py:192: RuntimeError
    
    opened by leshchenko1979 9
  • Runtime type validation?

    Runtime type validation?

    We are assessing a switch from typeguard to icontract for stricter runtime validation. However, I don't see anything akin to typeguard's @typechecked decorator. Correct me if I'm wrong, is the only way to do runtime type validation by making an @icontract.require(lambda arg: isinstance(arg, <type>) for all args?

    opened by crypdick 9
  • RecursionError due to contract checking during contract checking

    RecursionError due to contract checking during contract checking

    from typing import Any
    
    from icontract import DBC, ensure
    
    
    class Dimension(DBC):
        @ensure(lambda self, label, result: self.label(result) == label)
        def index(self, label: Any) -> int:
            return int(label)
    
        @ensure(lambda self, index, result: self.index(result) == index)
        def label(self, index: int) -> Any:
            return str(index)
    
    
    x = Dimension()
    print(x.label(0))
    

    This code results in a RecursionError, since while checking the postcondition for label the method index is invoked which triggers the check for the postcondition of index.

    It would be great if it were possible to suspend the checking of any other contracts while checking one contract, either by default or as a option when specifying the contract.

    opened by markusschmaus 9
  • License perms

    License perms

    When installing via pip. The license is placed in /usr/local

    ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied: '/usr/local/LICENSE.txt'
    Consider using the `--user` option or check the permissions.
    

    Maybe consider rename for global installation too LICENSE.icontract.txt (or subdirectory). Just a suggestion, keep up the good work!

    opened by ronaldpetty 6
  • Question/Feature request: Iterable usage in `require` and `snapshot` decorators

    Question/Feature request: Iterable usage in `require` and `snapshot` decorators

    Question

    How do I use Iterable in a @snapshot or in a @require decorator? I didn't find any hints in the documentation so I assume I either used them wrong or didn't understand a core concept. Otherwise, I would like to propose a feature request 😀

    Examples for @ensure

    If I try to take a snapshot of an Iterable, it is not possible since snapshot consumes it. Using the file iter_in_ensure.py

    # ––– file iter_in_ensure.py
    from collections.abc import Iterable
    from icontract import ensure, snapshot
    from more_itertools import always_iterable
    
    
    @snapshot(lambda i: list(i))
    @ensure(lambda result, OLD: set(OLD.i) == set(result))
    def ensure_iter(i: Iterable[int]) -> list[int]:
        return list(i)
    
    
    assert 1 == len(ensure_iter(always_iterable(1)))
    

    in a python environment where icontract and more_itertools is included, the error message is:

    $ python iter_in_ensure.py
    Traceback (most recent call last):
      File "iter_in_ensure.py", line 13, in <module>
        assert 1 == len(ensure_iter(always_iterable(1)))
      File "/…/icontract/_checkers.py", line 649, in wrapper
        raise violation_error
    icontract.errors.ViolationError: File iter_in_ensure.py, line 8 in <module>:
    set(OLD.i) == set(result):
    OLD was a bunch of OLD values
    OLD.i was [1]
    i was <tuple_iterator object at 0x7fe0fe9afb20>
    result was []
    set(OLD.i) was {1}
    set(result) was set()
    

    showing that the @snapshot decorator already consumed the iterator, leaving an empty result back. A possible workaround is to use itertools.tee inside the function:

    # ––– file fixup_ensure.py
    from collections.abc import Iterable
    from icontract import ensure
    from itertools import tee
    from more_itertools import always_iterable
    
    
    @ensure(lambda result: set(result[0]) == set(result[1]))
    def ensure_iter(i: Iterable[int]) -> tuple[list[int], Iterable[int]]:
        tee0, tee1 = tee(i, 2)
        return list(tee0), tee1
    
    
    assert 1 == len(ensure_iter(always_iterable(1))[0])
    

    but that requires to change the functions's signature for usage in @ensure only which – at least in my opinion – contradicts icontract's philosophy.

    Examples for @require

    With the @require decorator, I even didn't find a workaround:

    # ––– file iter_in_require.py
    from collections.abc import Iterable
    from icontract import require
    from more_itertools import always_iterable
    
    
    @require(lambda i: 1 == len(list(i)))
    def require_iter(i: Iterable[int]) -> list[int]:
        return list(i)
    
    
    length = len(require_iter(always_iterable(1)))
    assert 1 == length, f"result length was {length}"
    

    results in

    $ python iter_in_require.py
    Traceback (most recent call last):
      File "iter_in_require.py", line 13, in <module>
        assert 1 == length, f"result length was {length}"
    AssertionError: result length was 0
    

    showing that @require already consumed the iterator and the function require_iter has no chance to access it again.

    Versions

    • Python: Python 3.10.4
    • more-itertools: 8.13.0
    • icontract: 2.6.1

    Feature pitch

    If I didn't miss anything, there are features missing for the @snapshot and the @require function decorators. I suggest to introduce additional arguments to disable iterator consumption.

    A possible example usage for @snapshot:

    from collections.abc import Iterable
    from icontract import ensure, snapshot
    from more_itertools import always_iterable
    
    
    @snapshot(lambda i: list(i), iter='i')  # <- new argument 'iter'
    @ensure(lambda result, OLD: set(OLD.i) == set(result))
    def ensure_iter(i: Iterable[int]) -> list[int]:
        return list(i)
    
    
    assert 1 == len(ensure_iter(always_iterable(1)))
    

    A possible example usage for @require:

    from collections.abc import Iterable
    from icontract import require
    from more_itertools import always_iterable
    
    
    @require(lambda i: 1 == len(list(i)), iter='i')  # <- new argument 'iter'
    def require_iter(i: Iterable[int]) -> list[int]:
        return list(i)
    
    
    length = len(require_iter(always_iterable(1)))
    assert 1 == length, f"result length was {length}"
    

    The new argument iter indicates to use an independent iterator. In @require's case, it forwards it to the decorated function.

    I'm aware that the proposed solution is not applicable to all iterables, but I'm still convinced it would pose an improvement.

    opened by claudio-ebel 4
  • icontract fails to restore class invariants at method exit

    icontract fails to restore class invariants at method exit

    icontract fails to restore class invariants at method exit:

    import icontract
    
    @icontract.invariant(lambda self: self.x > 0)
    class A:
        def __init__(self):
            self.x = 1
        def f(self):
            self.x = -1
            raise ValueError
    
    a = A()
    assert a.x > 0  # ok
    try:
        a.f()
    except ValueError:
        pass
    assert a.x > 0  # AssertionError
    

    This is contrary to what Bertrand Meyer prescribes in his 1992 seminal article Applying “Design by Contract”:

    Any exception handling, whether for resumption or for organized panic, should restore the invariant.

    Class invariants are the minimal guarantees in case of failure.

    opened by maggyero 3
  • Mypy fails to determine function's type in icontract.ensure()

    Mypy fails to determine function's type in icontract.ensure()

    Bug Report When a type-annotated function is (re-)used in its own postcondition icontract.ensure decorator, mypy is not able to determine its type. Since mypy does successfully infers the types of an annotated function before the function's actual definition, this bug is part of the icontract library and not mypy.

    To Reproduce

    1. Create a file “bug.py” with this content:
      # ––– file: bug.py –––
      from icontract import ensure
      
      
      @ensure(lambda a, b, result: result == myadd(b, a), "Commutativity violated!")
      def myadd(a: int, b: int) -> int:
          return a + b
      
    2. Use mypy on it
      $ mypy --config-file= bug.py 
      bug.py:5: error: Cannot determine type of "myadd"
      Found 1 error in 1 file (checked 1 source file)
      

    Expected Behavior In general, mypy does not have a problem with using an annotated function before its definition. To see this,

    1. Create a file “no_bug.py” with this content:
      # ––– file: no_bug.py –––
      
      
      def use_before() -> int:
          return myadd(1, 2)  # used before def; like in bug.py
      
      
      def myadd(a: int, b: int) -> int:
          return a + b
      
    2. Use mypy on it
      $ mypy --config-file= no_bug.py 
      Success: no issues found in 1 source file
      

    Failed solution attempts Using a forward declaration of myadd did not help:

    1. Create a file “forward_decl.py” with this content:
      # ––– file forward_decl.py ––
      from icontract import ensure
      from typing import Callable, cast
      
      MyaddType = Callable[[int, int], int]
      
      
      @ensure(lambda a, b, result: result == cast(MyaddType, myadd)(b, a),
              "Commutativity violated!")
      def myadd(a: int, b: int) -> int:
          return a + b
      
    2. Use mypy on it
      $ mypy --config-file= forward_decl.py
      forward_decl.py:8: error: Cannot determine type of "myadd"
      Found 1 error in 1 file (checked 1 source file)
      

    An alternative use of a cast of myadd's return type did not help either:

    1. Create a file “return_type.py” with this content:
      # ––– file: return_type.py –––
      from icontract import ensure
      from typing import cast
      
      
      @ensure(lambda a, b, result: result == cast(bool, myadd(b, a)),
              "Commutativity violated!")
      def myadd(a: int, b: int) -> int:
          return a + b
      
    2. Use mypy on it
      $ mypy --config-file= return_type.py
      return_type.py:6: error: Cannot determine type of "myadd"
      Found 1 error in 1 file (checked 1 source file)
      

    Your Environment

    • Mypy version used: mypy 0.950 (compiled: yes)
    • Mypy command-line flags: --config-file=
    • icontract version used: icontract==2.6.1
    • Python version used: Python 3.10.4
    opened by claudio-ebel 6
Releases(v2.6.2)
A Regex based linter tool that works for any language and works exclusively with custom linting rules.

renag Documentation Available Here Short for Regex (re) Nag (like "one who complains"). Now also PEGs (Parsing Expression Grammars) compatible with py

Ryan Peach 12 Oct 20, 2022
A basic python project which replicates the functionalities on an 8 Ball.

Magic-8-Ball To the people who wish to make decisions using a Magic 8 Ball but can't get one? I gotchu. This is a basic python project which replicate

3 Jun 24, 2021
Check bookings for TUM libraries.

TUM Library Checker Only for educational purposes This repository contains a crawler to save bookings for TUM libraries in a CSV file. Sample data fro

Leon Blumenthal 3 Jan 27, 2022
Pipenv-local-deps-repro - Reproduction of a local transitive dependency on pipenv

Reproduction of the pipenv bug with transitive local dependencies. Clone this re

Lucas Duailibe 2 Jan 11, 2022
Plugin to manage site, circuit and device diagrams and documents in Netbox

Netbox Documents Plugin A plugin designed to faciliate the storage of site, circuit and device specific documents within NetBox Note: Netbox v3.2+ is

Jason Yates 38 Dec 24, 2022
Just another sentiment wrapper.

sentimany Just a simple sentiment tool. It just grabs a set of pre-made sentiment models that you can quickly use to attach sentiment scores to text.

vincent d warmerdam 15 Dec 27, 2022
Passenger Car Unit (PCU) Calculator

This is a streamlit web application which can be used to calculate Passenger Car Unit (PCU) values for a selected road section.

Dineth Dhananjaya 1 Apr 26, 2022
Store Simulation

Almacenes Para clonar el Repositorio: Vaya a la terminal de Linux o Mac, o a la cmd en Windows y ejecute:

Johan Posada 1 Nov 12, 2021
A faster Python generator that get function results from multi-process workers

multiyield This package implements a Python generator that get function results from multi-process workers. The faster_fifo Queue (instead of the stan

Xin Du 1 Nov 18, 2021
A tool to guide you for team selection based on mana and ruleset using your owned cards.

Splinterlands_Teams_Guide A tool to guide you for team selection based on mana and ruleset using your owned cards. Built With This project is built wi

Ruzaini Subri 3 Jul 30, 2022
Demo of patching a python context manager

patch-demo-20211203 demo of patching a python context manager poetry install poetry run python -m my_great_app to run the code poetry run pytest to te

Brad Smith 1 Feb 09, 2022
Бэкапалка таблиц mysql 8 через брокер сообщений nats

nats-mysql-tables-backup Бэкап таблиц mysql 8 через брокер сообщений nats (проверено и работает в ubuntu 20.04, при наличии python 3.8) ПРИМЕРЫ: Ниже

Constantine 1 Dec 13, 2021
A random cat fact python module

A random cat fact python module

Fayas Noushad 4 Nov 28, 2021
A guy with a lot of useful things to do when doing AtCoder in Python

atcoder_python_env Python で AtCoder をやるときに便利な諸々を用意したやつ コンテスト用フォルダの作成 セットアップ 自動テス

2 Dec 28, 2021
A small script I made that takes any standard Decklist of magic the gathering cards and pulls all card images from scryfall at once!

A small script I made that takes any standard Decklist of magic the gathering cards and pulls all card images from scryfall at once!

15 Aug 26, 2022
Slotscheck - Find mistakes in your slots definitions

🎰 Slotscheck Adding __slots__ to a class in Python is a great way to reduce mem

Arie Bovenberg 67 Dec 31, 2022
Beginner Projects A couple of beginner projects here

Beginner Projects A couple of beginner projects here, listed from easiest to hardest :) selector.py: simply a random selector to tell me who to faceti

Kylie 272 Jan 07, 2023
AdventOfCode 2021 solutions from the Devcord server

adventofcode-21 Ein Sammel-Repository für Advent of Code 2021-Lösungen der deutschen DevCord-Community. A repository collecting Advent of Code 2021 so

Devcord 12 Aug 26, 2022
Tips that improve your life in one way or another

Tips that improve your life in one way or another. This software downloads life tips from reddit.com/r/LifeProTips and tweet the most upvoted tips on Twitter.

Burak Tokman 2 Aug 04, 2022
Modify version of impacket wmiexec.py, get output(data,response) from registry, don't need SMB connection, also bypassing antivirus-software in lateral movement like WMIHACKER.

wmiexec-RegOut Modify version of impacket wmiexec.py,wmipersist.py. Got output(data,response) from registry, don't need SMB connection, but I'm in the

小离 228 Jan 04, 2023