GithubHelp home page GithubHelp logo

jazzband / contextlib2 Goto Github PK

View Code? Open in Web Editor NEW
37.0 37.0 15.0 167 KB

contextlib2 is a backport of the standard library's contextlib module to earlier Python versions.

Home Page: https://contextlib2.readthedocs.io

License: Other

Python 100.00%

contextlib2's People

Contributors

graingert avatar grzn avatar hugovk avatar jayvdb avatar jazzband-bot avatar jezdez avatar ncoghlan avatar ppentchev avatar webknjaz 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contextlib2's Issues

Decide how to backport 3.7 async context management support

Python 3.7 added async/await support to the contextlib module (e.g. asyncontextmanager and AsyncExitStack), and then Python 3.10 added more (e.g. aclosing).

This raised the question of how to backport those features to 3.6+ (the first version with support for yield inside async def).

The answer turned out to be "procrastinate on the question for 4+ years, so it became feasible to simply drop support for Python 3.5 and earlier, and use the async generator code as-is".

(Issue description updated Jun 2021 to describe what actually happened, rather than the more complicated alternatives I was considering to allow adding the new async features without dropping support for Python 3.5 and earlier)

backport contextlib from python 3.11

python/cpython@6cb145d

A TypeError is now raised instead of an AttributeError in contextlib.ExitStack.enter_context() and contextlib.AsyncExitStack.enter_async_context() for objects which do not support the context manager or asynchronous context manager protocols correspondingly. (Contributed by Serhiy Storchaka in bpo-44471.)

however this is only to match the change in behaviour of the async with and with statements in 3.11:

A TypeError is now raised instead of an AttributeError in with and async with statements for objects which do not support the context manager or asynchronous context manager protocols correspondingly. (Contributed by Serhiy Storchaka in bpo-12022.)

so would need conditional checking.

perhaps:

if sys.version_info >= (3, 11):
    from contextlib import ExitStack, AsyncExitStack
else:
    class ExitStack(...):
        ...

    class AsyncExitStack(...):
        ...

would be best?

Switch to CalVer and update supported versions

The next update is going to be a resync with the Python 3.10 version of contextlib2 to cover #12 and #27.

Rather than being 0.7.0, I'm going to make the version number 21.6.0, following a YY.M.X numbering scheme (year-month-serial).

I'm also going to make 0.6.0 the last version to support 3.5 and earlier, so the async features in later stdlib module iterations can be supported without any problems.

asynccontextmanager as decorator

The contextmanager decorated function can be used as decorator for sync functions. But asynccontextmanager decorated function cannot be used as decorator for async function. It would be nice to allow it

Rebase API for Python 3.7

I never got around to rebasing contextlib2 for Python 3.6, since the only thing added in that release was the AbstractContextManager ABC.

However, for 3.7 I've finally accepted https://bugs.python.org/issue10049, which adds a dedicated nullcontext context manager to contextlib as a simpler and faster alternative to using ExitStack to manage single optional context managers.

There's also the new asyncontextmanager API, but adding that will be somewhat tricky: #12

0.6.0.post1: pytest is failing

Just normal build, install and test cycle used on building package from non-root account:

  • "setup.py build"
  • "setup.py install --root </install/prefix>"
  • "pytest with PYTHONPATH pointing to setearch and sitelib inside </install/prefix>
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-contextlib2-0.6.0.post1-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-contextlib2-0.6.0.post1-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ PYTHONDONTWRITEBYTECODE=1
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
benchmark: 3.4.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/tkloczko/rpmbuild/BUILD/contextlib2-0.6.0.post1
plugins: forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, expect-1.1.0, httpbin-1.0.0, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, freezegun-0.4.2, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, asyncio-0.15.1, toolbox-0.5, xprocess-0.17.1, aiohttp-0.3.0, checkdocs-2.7.0, mock-3.6.1, rerunfailures-9.1.1, requests-mock-1.9.3, cov-2.12.1, pyfakefs-4.5.0, cases-3.6.1, flaky-3.7.0, hypothesis-6.14.0, benchmark-3.4.1, xdist-2.3.0, Faker-8.8.1
collected 81 items

. .                                                                                                                                                                  [  1%]
test_contextlib2.py ...............................................FFFFFFF.........................                                                                  [100%]

================================================================================= FAILURES =================================================================================
__________________________________________________________________ TestRedirectStream.test_instance_docs ___________________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff603109fd0>

    @requires_docstrings
    def test_instance_docs(self):
        # Issue 19330: ensure context manager instances have good docstrings
        cm_docstring = self.redirect_stream.__doc__
>       obj = self.redirect_stream(None)
E       TypeError: 'NoneType' object is not callable

test_contextlib2.py:842: TypeError
_______________________________________________________________ TestRedirectStream.test_no_redirect_in_init ________________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff6028e6d00>

    def test_no_redirect_in_init(self):
>       orig_stdout = getattr(sys, self.orig_stream)
E       TypeError: getattr(): attribute name must be string

test_contextlib2.py:846: TypeError
______________________________________________________________ TestRedirectStream.test_redirect_to_string_io _______________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff602845340>

    def test_redirect_to_string_io(self):
        f = io.StringIO()
        msg = "Consider an API like help(), which prints directly to stdout"
>       orig_stdout = getattr(sys, self.orig_stream)
E       TypeError: getattr(): attribute name must be string

test_contextlib2.py:853: TypeError
______________________________________________________________ TestRedirectStream.test_enter_result_is_target ______________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff602645520>

    def test_enter_result_is_target(self):
        f = io.StringIO()
>       with self.redirect_stream(f) as enter_result:
E       TypeError: 'NoneType' object is not callable

test_contextlib2.py:862: TypeError
__________________________________________________________________ TestRedirectStream.test_cm_is_reusable __________________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff602845760>

    def test_cm_is_reusable(self):
        f = io.StringIO()
>       write_to_f = self.redirect_stream(f)
E       TypeError: 'NoneType' object is not callable

test_contextlib2.py:867: TypeError
_________________________________________________________________ TestRedirectStream.test_cm_is_reentrant __________________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff6021ed070>

    def test_cm_is_reentrant(self):
        f = io.StringIO()
>       write_to_f = self.redirect_stream(f)
E       TypeError: 'NoneType' object is not callable

test_contextlib2.py:879: TypeError
____________________________________________________________ TestRedirectStream.test_cm_is_exitstack_compatible ____________________________________________________________

self = <test_contextlib2.TestRedirectStream object at 0x7ff6028667f0>

    def test_cm_is_exitstack_compatible(self):
        with ExitStack() as stack:
            # This shouldn't raise an exception.
>           stack.enter_context(self.redirect_stream(io.StringIO()))
E           TypeError: 'NoneType' object is not callable

test_contextlib2.py:892: TypeError
========================================================================= short test summary info ==========================================================================
FAILED test_contextlib2.py::TestRedirectStream::test_instance_docs - TypeError: 'NoneType' object is not callable
FAILED test_contextlib2.py::TestRedirectStream::test_no_redirect_in_init - TypeError: getattr(): attribute name must be string
FAILED test_contextlib2.py::TestRedirectStream::test_redirect_to_string_io - TypeError: getattr(): attribute name must be string
FAILED test_contextlib2.py::TestRedirectStream::test_enter_result_is_target - TypeError: 'NoneType' object is not callable
FAILED test_contextlib2.py::TestRedirectStream::test_cm_is_reusable - TypeError: 'NoneType' object is not callable
FAILED test_contextlib2.py::TestRedirectStream::test_cm_is_reentrant - TypeError: 'NoneType' object is not callable
FAILED test_contextlib2.py::TestRedirectStream::test_cm_is_exitstack_compatible - TypeError: 'NoneType' object is not callable
======================================================================= 7 failed, 73 passed in 7.07s =======================================================================

setup.py does not fallback to using distutils.core import setup

In all of the setup.py scripts I have used before, the import for setup is like this:

try:
from setuptools import setup
except ImportError:
from distutils.core import setup

Which allows it to fall back to distutils.core if setuptools is not available.

Is there a reason that this is missing from this projects setup.py?

Thanks.

21.6.0: mypy errors

$ python -m mypy.stubtest --allowlist dev/mypy.allowlist contextlib2
error: not checking stubs due to mypy build errors:
contextlib2/__init__.pyi:41: error: Class contextlib2._GeneratorContextManager has abstract attributes "__exit__"  [misc]
contextlib2/__init__.pyi:41: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
contextlib2/__init__.pyi:55: error: Class contextlib2.closing has abstract attributes "__exit__"  [misc]
contextlib2/__init__.pyi:55: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
contextlib2/__init__.pyi:62: error: Class contextlib2.aclosing has abstract attributes "__aexit__"  [misc]
contextlib2/__init__.pyi:62: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
contextlib2/__init__.pyi:74: error: Class contextlib2.redirect_stdout has abstract attributes "__exit__"  [misc]
contextlib2/__init__.pyi:74: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
contextlib2/__init__.pyi:77: error: Class contextlib2.redirect_stderr has abstract attributes "__exit__"  [misc]
contextlib2/__init__.pyi:77: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
contextlib2/__init__.pyi:116: error: Return type "Awaitable[AsyncExitStack]" of "__aenter__" incompatible with return type "Coroutine[Any, Any, AsyncExitStack]" in supertype "AbstractAsyncContextManager"  [override]
contextlib2/__init__.pyi:117: error: Return type "Awaitable[bool]" of "__aexit__" incompatible with return type "Coroutine[Any, Any, Optional[bool]]" in supertype "AbstractAsyncContextManager"  [override]
$

python3.11 support?

Hello,

The next stable release of Debian includes Python 3.11 (and might make Python 3.11 the default version)

Running the unit tests from version 0.6.0 or version 21.6.0 under Python 3.11 produces the following errors:

======================================================================
ERROR: test_typo_enter (test.test_contextlib.TestContextDecorator.test_typo_enter)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/autopkgtest.oVLsYe/build.IvE/src/test/test_contextlib.py", line 498, in test_typo_enter
    with mycontext():
TypeError: 'mycontext' object does not support the context manager protocol

======================================================================
ERROR: test_typo_exit (test.test_contextlib.TestContextDecorator.test_typo_exit)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/autopkgtest.oVLsYe/build.IvE/src/test/test_contextlib.py", line 510, in test_typo_exit
    with mycontext():
TypeError: 'mycontext' object does not support the context manager protocol (missed __exit__ method)

----------------------------------------------------------------------

Any guidance on how we can patch contextlib2 version 21.6.0 to fix this?

Thanks!

Initial Update

The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.

Use mypy.stubtest in CI

(Derived from python/mypy#5028 (comment))

The current mypy CI check just tests that the stub file is well formed, it doesn't test that the module API actually matches the type hinted stub API. Running mypy.stubcheck instead will fix that testing gap, but the failures need to be fixed first:

[ncoghlan@thechalk contextlib2]$ python3 -m mypy.stubtest contextlib2
error: contextlib2.ContextDecorator.refresh_cm is not present in stub
Stub:
MISSING
Runtime: at line 76 in file /home/ncoghlan/devel/contextlib2/contextlib2/__init__.py
<function ContextDecorator.refresh_cm at 0x7fd497b61dc0>

error: contextlib2.ContextStack is not present in stub
Stub:
MISSING
Runtime: at line 783 in file /home/ncoghlan/devel/contextlib2/contextlib2/__init__.py
<class 'contextlib2.ContextStack'>

error: contextlib2.nullcontext is not a function
Stub: at line 122
Overload(def [_T] (enter_result: _T`-1) -> typing.ContextManager[_T`-1], def () -> typing.ContextManager[None])
Runtime: at line 755 in file /home/ncoghlan/devel/contextlib2/contextlib2/__init__.py
<class 'contextlib2.nullcontext'>

ExitStack fails with StreamReader / StreamWriter

In Python 2.7, StreamReader and StreamWriter are context managers that wrap around a stream and handle encoding issue. However, the type of one of these objects is instance, not file. As a result, ExitStack.enter_context with AttributeError when one of these is added to the stack:

MWE:

# -*- coding: utf-8 -*-
from contextlib2 import ExitStack
from codecs import getreader

with open('test_file', 'wb') as f:
    f.write(u'いちりきつくっ'.encode('UTF-8'))

reader = getreader('utf-8')
with reader(open('test_file', 'r')) as f:
    print(f.read())  # いちりきつくっ

try:
    with ExitStack() as stack:
        f = stack.enter_context(reader(open('test_file', 'r'))) # Error
        print(f.read())
finally:
    import os
    os.unlink('test_file')    # Delete the file

Here is the result:

AttributeError: type object 'instance' has no attribute '__exit__'

Not sure what happens on Python 3, since Python 3's native unicode support obviates the need for the StreamReader in the first place as far as I can tell.

I don't know if this is a good solution, but if you use cm.__class__ instead of type(cm), it seems to work OK:

    def enter_context(self, cm):
        """Enters the supplied context manager

        If successful, also pushes its __exit__ method as a callback and
        returns the result of the __enter__ method.
        """
        # We look up the special methods on the type to match the with statement
        for _cm_type in type(cm), cm.__class__:
            try:
                _exit = _cm_type.__exit__
                result = _cm_type.__enter__(cm)
            except AttributeError as e:
                error = e
                continue

            error = None
            break

        if error is not None:
            raise error        

        self._push_cm_exit(cm, _exit)
        return result

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.