diff --git a/contextlib/contextlib.py b/contextlib/contextlib.py index b3c1025b..4bcd437b 100644 --- a/contextlib/contextlib.py +++ b/contextlib/contextlib.py @@ -8,101 +8,7 @@ Not implemented: """ -class ContextDecorator(object): - "A base class or mixin that enables context managers to work as decorators." - - def _recreate_cm(self): - """Return a recreated instance of self. - - Allows an otherwise one-shot context manager like - _GeneratorContextManager to support use as - a decorator via implicit recreation. - - This is a private interface just for _GeneratorContextManager. - See issue #11647 for details. - """ - return self - - def __call__(self, func): - def inner(*args, **kwds): - with self._recreate_cm(): - return func(*args, **kwds) - return inner - - -class _GeneratorContextManager(ContextDecorator): - """Helper for @contextmanager decorator.""" - - def __init__(self, func, *args, **kwds): - self.gen = func(*args, **kwds) - self.func, self.args, self.kwds = func, args, kwds - - def _recreate_cm(self): - # _GCM instances are one-shot context managers, so the - # CM must be recreated each time a decorated function is - # called - return self.__class__(self.func, *self.args, **self.kwds) - - def __enter__(self): - try: - return next(self.gen) - except StopIteration: - raise RuntimeError("generator didn't yield") from None - - def __exit__(self, type, value, traceback): - if type is None: - try: - next(self.gen) - except StopIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - if value is None: - # Need to force instantiation so we can reliably - # tell if we get the same exception back - value = type() - try: - self.gen.throw(type, value, traceback) - raise RuntimeError("generator didn't stop after throw()") - except StopIteration as exc: - # Suppress the exception *unless* it's the same exception that - # was passed to throw(). This prevents a StopIteration - # raised inside the "with" statement from being suppressed - return exc is not value - - -def contextmanager(func): - """@contextmanager decorator. - - Typical usage: - - @contextmanager - def some_generator(): - - try: - yield - finally: - - - This makes this: - - with some_generator() as : - - - equivalent to this: - - - try: - = - - finally: - - - """ - def helper(*args, **kwds): - return _GeneratorContextManager(func, *args, **kwds) - return helper +from ucontextlib import * class closing(object): diff --git a/contextlib/metadata.txt b/contextlib/metadata.txt index ca7db6d3..2554e728 100644 --- a/contextlib/metadata.txt +++ b/contextlib/metadata.txt @@ -1,4 +1,5 @@ srctype = cpython type = module -version = 3.4.2-1 +version = 3.4.2-2 long_desc = Port of contextlib for micropython +depends = ucontextlib diff --git a/contextlib/setup.py b/contextlib/setup.py index 75ab598f..cf4da674 100644 --- a/contextlib/setup.py +++ b/contextlib/setup.py @@ -6,7 +6,7 @@ from setuptools import setup setup(name='micropython-contextlib', - version='3.4.2-1', + version='3.4.2-2', description='CPython contextlib module ported to MicroPython', long_description='This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.', url='https://github.com/micropython/micropython/issues/405', @@ -15,4 +15,5 @@ setup(name='micropython-contextlib', maintainer='MicroPython Developers', maintainer_email='micro-python@googlegroups.com', license='Python', - py_modules=['contextlib']) + py_modules=['contextlib'], + install_requires=['micropython-ucontextlib']) diff --git a/contextlib/tests.py b/contextlib/tests.py index 019266d7..3473fc2f 100644 --- a/contextlib/tests.py +++ b/contextlib/tests.py @@ -1,38 +1,8 @@ -from unittest import TestCase, run_class -from contextlib import contextmanager, closing, suppress +import unittest +from contextlib import closing, suppress -class ContextManagerTestCase(TestCase): - - def setUp(self): - self._history = [] - - @contextmanager - def manager(x): - self._history.append('start') - try: - yield x - finally: - self._history.append('finish') - - self._manager = manager - - def test_context_manager(self): - with self._manager(123) as x: - self.assertEqual(x, 123) - self.assertEqual(self._history, ['start', 'finish']) - - def test_context_manager_on_error(self): - exc = Exception() - try: - with self._manager(123) as x: - raise exc - except Exception as e: - self.assertEqual(exc, e) - self.assertEqual(self._history, ['start', 'finish']) - - -class ClosingTestCase(TestCase): +class ClosingTestCase(unittest.TestCase): class Closable: def __init__(self): @@ -58,7 +28,7 @@ class ClosingTestCase(TestCase): self.assertTrue(closable.closed) -class SuppressTestCase(TestCase): +class SuppressTestCase(unittest.TestCase): def test_suppress(self): with suppress(ValueError, TypeError): @@ -68,6 +38,4 @@ class SuppressTestCase(TestCase): if __name__ == '__main__': - run_class(ContextManagerTestCase) - run_class(ClosingTestCase) - run_class(SuppressTestCase) + unittest.main()