Code Monkey home page Code Monkey logo

picobox's People

Contributors

ikalnytskyi avatar malor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

picobox's Issues

current release has test failures when building with Python 3.10

============================= test session starts ==============================
platform linux -- Python 3.10.6, pytest-7.1.2, pluggy-1.0.0
rootdir: /build/source
collected 1266 items                                                           

tests/test_box.py ...................................................... [  4%]
........................................................................ [  9%]
........................................................................ [ 15%]
........FF............                                                   [ 17%]
tests/test_scopes.py s.................................................. [ 21%]
........................................................................ [ 27%]
........................................................................ [ 32%]
........................................................................ [ 38%]
........................................................................ [ 44%]
................................                                         [ 46%]
tests/test_stack.py .................................................... [ 50%]
........................................................................ [ 56%]
........................................................................ [ 62%]
........................................................................ [ 67%]
........................................................................ [ 73%]
........................................................................ [ 79%]
..........................................................FFFF.......... [ 84%]
..............                                                           [ 86%]
tests/contrib/test_flaskscopes.py ...................................... [ 89%]
........................................................................ [ 94%]
...................................................................      [100%]

=================================== FAILURES ===================================
____________________ test_box_pass_unexpected_argument[Box] ____________________

boxclass = <class 'picobox._box.Box'>

    def test_box_pass_unexpected_argument(boxclass):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @testbox.pass_('d')
        def fn(a, b):
            return a + b
    
        with pytest.raises(TypeError) as excinfo:
            fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_box.py:371: AssertionError
_________________ test_box_pass_unexpected_argument[ChainBox] __________________

boxclass = <class 'picobox._box.ChainBox'>

    def test_box_pass_unexpected_argument(boxclass):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @testbox.pass_('d')
        def fn(a, b):
            return a + b
    
        with pytest.raises(TypeError) as excinfo:
            fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_box.py:371: AssertionError
______________ test_box_pass_unexpected_argument[Box-teststack0] _______________

boxclass = <class 'picobox._box.Box'>, teststack = <Stack (0x7ffff64c56f0)>

    def test_box_pass_unexpected_argument(boxclass, teststack):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @teststack.pass_('d')
        def fn(a, b):
            return a + b
    
        with teststack.push(testbox):
            with pytest.raises(TypeError) as excinfo:
                fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_stack.py:437: AssertionError
________________ test_box_pass_unexpected_argument[Box-picobox] ________________

boxclass = <class 'picobox._box.Box'>
teststack = <module 'picobox' from '/nix/store/322w5r8nncx3yhms0aaslyf72pv0632d-python3.10-picobox-2.2.0/lib/python3.10/site-packages/picobox/__init__.py'>

    def test_box_pass_unexpected_argument(boxclass, teststack):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @teststack.pass_('d')
        def fn(a, b):
            return a + b
    
        with teststack.push(testbox):
            with pytest.raises(TypeError) as excinfo:
                fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_stack.py:437: AssertionError
____________ test_box_pass_unexpected_argument[ChainBox-teststack0] ____________

boxclass = <class 'picobox._box.ChainBox'>, teststack = <Stack (0x7ffff64c56f0)>

    def test_box_pass_unexpected_argument(boxclass, teststack):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @teststack.pass_('d')
        def fn(a, b):
            return a + b
    
        with teststack.push(testbox):
            with pytest.raises(TypeError) as excinfo:
                fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_stack.py:437: AssertionError
_____________ test_box_pass_unexpected_argument[ChainBox-picobox] ______________

boxclass = <class 'picobox._box.ChainBox'>
teststack = <module 'picobox' from '/nix/store/322w5r8nncx3yhms0aaslyf72pv0632d-python3.10-picobox-2.2.0/lib/python3.10/site-packages/picobox/__init__.py'>

    def test_box_pass_unexpected_argument(boxclass, teststack):
        testbox = boxclass()
        testbox.put('d', 10)
    
        @teststack.pass_('d')
        def fn(a, b):
            return a + b
    
        with teststack.push(testbox):
            with pytest.raises(TypeError) as excinfo:
                fn(1, 2)
    
>       assert str(excinfo.value) == "fn() got an unexpected keyword argument 'd'"
E       assert "test_box_pas... argument 'd'" == "fn() got an ... argument 'd'"
E         - fn() got an unexpected keyword argument 'd'
E         + test_box_pass_unexpected_argument.<locals>.fn() got an unexpected keyword argument 'd'

tests/test_stack.py:437: AssertionError
=============================== warnings summary ===============================
tests/test_scopes.py: 13 warnings
  /build/source/tests/test_scopes.py:61: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
    coroutine_function = asyncio.coroutine(coroutine_function)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/test_box.py::test_box_pass_unexpected_argument[Box] - assert "te...
FAILED tests/test_box.py::test_box_pass_unexpected_argument[ChainBox] - asser...
FAILED tests/test_stack.py::test_box_pass_unexpected_argument[Box-teststack0]
FAILED tests/test_stack.py::test_box_pass_unexpected_argument[Box-picobox] - ...
FAILED tests/test_stack.py::test_box_pass_unexpected_argument[ChainBox-teststack0]
FAILED tests/test_stack.py::test_box_pass_unexpected_argument[ChainBox-picobox]
============ 6 failed, 1259 passed, 1 skipped, 13 warnings in 2.08s ============

The same tests pass with Python 3.9 without problems.

Add `picobox.ext.enterprise` extension

One thing I regret about picobox is that it uses non-conventional names for methods (e.g. pass_(), not inject) and classes (e.g. Box, not Container). I'm afraid it might be a too late to change the names.

That's why it's worth considering introducing some picobox.ext.enterprise extension that can expose better names.

How can it look like?

import picobox.ext.enterprise as di
import requests


@di.inject("conf")
@di.inject("requests", as_="session")
def get_resource(uri, session, conf):
    return session.get(conf["base_uri"] + uri)


container = di.Container()
container.add("conf", {"base_uri": "http://example.com"})
container.add("requests", factory=requests.Session, scope=picobox.threadlocal)

with di.use(container):
    get_resource("/resource", requests.Session(), {})
    get_resource("/resource", requests.Session())
    get_resource("/resource")

Add `picobox.ext.starlettescopes` extension

Starlette is a lightweight framework/toolkit for building web services in Python. Many Python frameworks are built on top of Starlette (e.g. FastAPI). It'd be nice if Picobox can come with application/request scopes for Starlette web applications, since this way we can cover many frameworks at once.

Add `picobox.ext.fastapiscopes` extension

FastAPI is one of the popular (if not most popular) asynchronous web frameworks for Python. It'd be nice if Picobox can come with application/request scopes for FastAPI web applications.

Test failures with Python 3.11

With e92b001:

$ tox -e py311
py311: install_deps> python -I -m pip install flask pytest
.pkg: install_requires> python -I -m pip install 'setuptools>=40.8.0' wheel
.pkg: _optional_hooks> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
.pkg: get_requires_for_build_sdist> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
.pkg: install_requires_for_build_sdist> python -I -m pip install setuptools_scm
.pkg: prepare_metadata_for_build_wheel> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
.pkg: build_sdist> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
py311: install_package> python -I -m pip install --force-reinstall --no-deps /tmp/picobox/.tox/.tmp/package/1/picobox-2.2.1.dev34+ge92b001.tar.gz
py311: commands[0]> .tox/py311/bin/python -m pytest --strict
========================================================= test session starts =========================================================
platform linux -- Python 3.11.2, pytest-7.2.1, pluggy-1.0.0
cachedir: .tox/py311/.pytest_cache
rootdir: /tmp/picobox
collected 1266 items                                                                                                                  

tests/test_box.py ............................................................................................................. [  8%]
...............................................................................................................                 [ 17%]
tests/test_scopes.py s......................................................................................................... [ 25%]
............................................................................................................................... [ 35%]
...............................................................................................................F.F...F..F..F..F [ 45%]
..F..F...F.                                                                                                                     [ 46%]
tests/test_stack.py ........................................................................................................... [ 55%]
............................................................................................................................... [ 65%]
............................................................................................................................... [ 75%]
............................................................................................................................... [ 85%]
..........                                                                                                                      [ 86%]
tests/contrib/test_flaskscopes.py ............................................................................................. [ 93%]
....................................................................................                                            [100%]

============================================================== FAILURES ===============================================================
__________________________________________ test_scope_value_shared[singleton-exec_coroutine] __________________________________________

request = <FixtureRequest for <Function test_scope_value_shared[singleton-exec_coroutine]>>, scopename = 'singleton'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("singleton", "exec_thread"),
            ("singleton", "exec_coroutine"),
            ("singleton", "exec_context"),
            ("threadlocal", "exec_coroutine"),
            ("threadlocal", "exec_context"),
        ],
    )
    def test_scope_value_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
>       exec_(scope.set, "the-key", value)

tests/test_scopes.py:195: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <bound method singleton.set of <picobox._scopes.singleton object at 0x7fe02d2cdf90>>
args = ('the-key', <object object at 0x7fe02e2b18f0>), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
_________________________________________ test_scope_value_shared[threadlocal-exec_coroutine] _________________________________________

request = <FixtureRequest for <Function test_scope_value_shared[threadlocal-exec_coroutine]>>, scopename = 'threadlocal'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("singleton", "exec_thread"),
            ("singleton", "exec_coroutine"),
            ("singleton", "exec_context"),
            ("threadlocal", "exec_coroutine"),
            ("threadlocal", "exec_context"),
        ],
    )
    def test_scope_value_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
>       exec_(scope.set, "the-key", value)

tests/test_scopes.py:195: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <bound method threadlocal.set of <picobox._scopes.threadlocal object at 0x7fe02c9eb4d0>>
args = ('the-key', <object object at 0x7fe02e2b29a0>), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
_______________________________________ test_scope_value_not_shared[contextvars-exec_coroutine] _______________________________________

request = <FixtureRequest for <Function test_scope_value_not_shared[contextvars-exec_coroutine]>>, scopename = 'contextvars'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("threadlocal", "exec_thread"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
            ("noscope", "exec_thread"),
            ("noscope", "exec_coroutine"),
            ("noscope", "exec_context"),
        ],
    )
    def test_scope_value_not_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
>       exec_(scope.set, "the-key", value)

tests/test_scopes.py:216: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <bound method contextvars.set of <picobox._scopes.contextvars object at 0x7fe02ca3cf90>>
args = ('the-key', <object object at 0x7fe02e2b2200>), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
_________________________________________ test_scope_value_not_shared[noscope-exec_coroutine] _________________________________________

request = <FixtureRequest for <Function test_scope_value_not_shared[noscope-exec_coroutine]>>, scopename = 'noscope'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("threadlocal", "exec_thread"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
            ("noscope", "exec_thread"),
            ("noscope", "exec_coroutine"),
            ("noscope", "exec_context"),
        ],
    )
    def test_scope_value_not_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
>       exec_(scope.set, "the-key", value)

tests/test_scopes.py:216: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <bound method noscope.set of <picobox._scopes.noscope object at 0x7fe02c9e9410>>
args = ('the-key', <object object at 0x7fe02e2b1850>), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
_____________________________________ test_scope_value_downstack_shared[singleton-exec_coroutine] _____________________________________

request = <FixtureRequest for <Function test_scope_value_downstack_shared[singleton-exec_coroutine]>>, scopename = 'singleton'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("singleton", "exec_thread"),
            ("singleton", "exec_coroutine"),
            ("singleton", "exec_context"),
            ("threadlocal", "exec_thread"),
            ("threadlocal", "exec_coroutine"),
            ("threadlocal", "exec_context"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
        ],
    )
    def test_scope_value_downstack_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
        def caller():
            scope.set("the-key", value)
            return callee()
    
        def callee():
            return scope.get("the-key")
    
>       assert exec_(caller) is value

tests/test_scopes.py:248: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <function test_scope_value_downstack_shared.<locals>.caller at 0x7fe02c9ce340>, args = (), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
____________________________________ test_scope_value_downstack_shared[threadlocal-exec_coroutine] ____________________________________

request = <FixtureRequest for <Function test_scope_value_downstack_shared[threadlocal-exec_coroutine]>>, scopename = 'threadlocal'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("singleton", "exec_thread"),
            ("singleton", "exec_coroutine"),
            ("singleton", "exec_context"),
            ("threadlocal", "exec_thread"),
            ("threadlocal", "exec_coroutine"),
            ("threadlocal", "exec_context"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
        ],
    )
    def test_scope_value_downstack_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
        def caller():
            scope.set("the-key", value)
            return callee()
    
        def callee():
            return scope.get("the-key")
    
>       assert exec_(caller) is value

tests/test_scopes.py:248: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <function test_scope_value_downstack_shared.<locals>.caller at 0x7fe02c9cf4c0>, args = (), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
____________________________________ test_scope_value_downstack_shared[contextvars-exec_coroutine] ____________________________________

request = <FixtureRequest for <Function test_scope_value_downstack_shared[contextvars-exec_coroutine]>>, scopename = 'contextvars'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("singleton", "exec_thread"),
            ("singleton", "exec_coroutine"),
            ("singleton", "exec_context"),
            ("threadlocal", "exec_thread"),
            ("threadlocal", "exec_coroutine"),
            ("threadlocal", "exec_context"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
        ],
    )
    def test_scope_value_downstack_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
        def caller():
            scope.set("the-key", value)
            return callee()
    
        def callee():
            return scope.get("the-key")
    
>       assert exec_(caller) is value

tests/test_scopes.py:248: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <function test_scope_value_downstack_shared.<locals>.caller at 0x7fe02c9ceb60>, args = (), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
____________________________________ test_scope_value_downstack_not_shared[noscope-exec_coroutine] ____________________________________

request = <FixtureRequest for <Function test_scope_value_downstack_not_shared[noscope-exec_coroutine]>>, scopename = 'noscope'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("noscope", "exec_thread"),
            ("noscope", "exec_coroutine"),
            ("noscope", "exec_context"),
        ],
    )
    def test_scope_value_downstack_not_shared(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        value = object()
        exec_ = request.getfixturevalue(executor)
    
        def caller():
            scope.set("the-key", value)
            return callee()
    
        def callee():
            return scope.get("the-key")
    
        with pytest.raises(KeyError, match="the-key"):
>           exec_(caller)

tests/test_scopes.py:272: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <function test_scope_value_downstack_not_shared.<locals>.caller at 0x7fe02ca147c0>, args = (), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
__________________________________________ test_scope_not_leaked[contextvars-exec_coroutine] __________________________________________

request = <FixtureRequest for <Function test_scope_not_leaked[contextvars-exec_coroutine]>>, scopename = 'contextvars'
executor = 'exec_coroutine'

    @pytest.mark.parametrize(
        "scopename, executor",
        [
            ("threadlocal", "exec_thread"),
            ("contextvars", "exec_thread"),
            ("contextvars", "exec_coroutine"),
            ("contextvars", "exec_context"),
        ],
    )
    def test_scope_not_leaked(request, scopename, executor):
        scope = request.getfixturevalue(scopename)
        exec_ = request.getfixturevalue(executor)
    
        scope.set("a-key", "a-value")
>       exec_(scope.set, "the-key", "the-value")

tests/test_scopes.py:289: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

coroutine_function = <bound method contextvars.set of <picobox._scopes.contextvars object at 0x7fe02ca48dd0>>
args = ('the-key', 'the-value'), kwargs = {}

    def executor(coroutine_function, *args, **kwargs):
        if not asyncio.iscoroutinefunction(coroutine_function):
>           coroutine_function = asyncio.coroutine(coroutine_function)
E           AttributeError: module 'asyncio' has no attribute 'coroutine'

tests/test_scopes.py:63: AttributeError
========================================================== warnings summary ===========================================================
.tox/py311/lib/python3.11/site-packages/_pytest/config/__init__.py:1240
  /tmp/picobox/.tox/py311/lib/python3.11/site-packages/_pytest/config/__init__.py:1240: PytestRemovedIn8Warning: The --strict option is deprecated, use --strict-markers instead.
    self.issue_config_time_warning(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
======================================================= short test summary info =======================================================
FAILED tests/test_scopes.py::test_scope_value_shared[singleton-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_shared[threadlocal-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_not_shared[contextvars-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_not_shared[noscope-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_downstack_shared[singleton-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_downstack_shared[threadlocal-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_downstack_shared[contextvars-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_value_downstack_not_shared[noscope-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
FAILED tests/test_scopes.py::test_scope_not_leaked[contextvars-exec_coroutine] - AttributeError: module 'asyncio' has no attribute 'coroutine'
======================================== 9 failed, 1256 passed, 1 skipped, 1 warning in 2.01s =========================================
py311: exit 1 (2.29 seconds) /tmp/picobox> .tox/py311/bin/python -m pytest --strict pid=63011
.pkg: _exit> python /usr/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
  py311: FAIL code 1 (12.79=setup[10.50]+cmd[2.29] seconds)
  evaluation failed :( (12.87 seconds)

Add type hints

Since I don't like type hints specified in the code base, I need to check how to add them via *.pyi stubs.

Add `picobox.ext.asgiscopes` extension

Ever since I started working on scopes for Starlette web framework (see #77), I realized that there's no Starlette specific facilities (like Flask provides) to access application or request states from any point of execution.

Thus, I'll need to go through a special ASGI middleware to define those scopes, and this approach will work for any ASGI framework.

At this point I'm thinking about three types of scopes: application and request scopes. The middleware must be recommended to be a top-level (or the most outer middleware), and it must save both the current ASGI application and current request context in a global contextvar variable.

Add `picobox.ext.wsgiscopes` extension

When I was working on ASGI scopes (see #80), I realized that the same approach (i.e. by using a middleware) can be applied to any WSGI-based web framework. In order to support as many WSGI web frameworks as possible, we have to provide these generic scopes.

At this point I'm thinking about two type of scopes: application and request scopes. The middleware must be recommended to be a top-level (or the most outer middleware), and it must save both the current WSGI application and current request context in a global threadlocal variable.

Add coroutine functions support to `pass_` decorator

Currently the picobox.pass_() decorator can be successfully applied to coroutine functions, and such a coroutine function can be successfully used. For instance, the following code works as expected:

@picobox.pass_("database_session")
async def get_movies_by_name(name: str, database_conn: DatabaseSession) -> list[Movie]:
    return await database_conn.query(...)

# ...

await get_movies_by_name("The Batman")

The get_movies_by_name coroutine function, however, lose its coroutine function marker, which may lead to undesired consequences when used with frameworks or libraries that support both sync and async interface, and use inspect.iscoroutinefunction() to properly dispatch its execution (e.g. Starlette).

>>> inspect.iscoroutinefunction(get_movies_by_name)
False

Add `picobox.ext.autowire` extension

Autowiring is convenient functionality that allows to inject dependencies implicitly. Picobox core provides everything that is required to implement autowiring functionality as a third party decorator in picobox.contrib pacakge.

The autowiring decorator must satisfy the following requirements:

  1. It must autowire by names.
  2. It must autowire by types.
  3. Autowiring by names and types are mutually exclusive.

Add `picobox.ext.declarative` extension

There are engineers who prefer declarative over imperative, even when it comes to defining DI containers (i.e. picobox.Box).

import picobox.ext.declarative as declarative

class MyBox(declarative.Box):
  ...

RFE: is it possible to start making github releases?๐Ÿค”

Is it possible next time on release new version make the github release to have entry on https://github.com/ikalnytskyi/picobox/releases? ๐Ÿค”

I'm asking because only on make gh release is spread notification about new release to those who have set watch->releases.
My automation process those notification trying make preliminary automated upgrade of building packages which allow save some time on maintaining packaging procedures.

More about gh releases is possible to find on
https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
https://github.com/marketplace/actions/github-release
https://pgjones.dev/blog/trusted-plublishing-2023/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.