Merge branch 'master' into pyup-update-wheel-0.30.0-to-0.31.0 pyup-update-wheel-0.30.0-to-0.31.0
authorDaniel Roy Greenfeld <pydanny@users.noreply.github.com>
Sun, 8 Apr 2018 22:59:00 +0000 (17:59 -0500)
committerGitHub <noreply@github.com>
Sun, 8 Apr 2018 22:59:00 +0000 (17:59 -0500)
12 files changed:
.travis.yml
CONTRIBUTING.rst
HISTORY.rst
README.rst
cached_property.py
conftest.py
requirements.txt
setup.py
tests/test_async_cached_property.py
tests/test_cached_property.py
tests/test_coroutine_cached_property.py
tox.ini

index 41eb570c32f82c8289bb7568af460e47e14cf703..0fe543ef72799515317f96d706804805edd26f7a 100644 (file)
@@ -14,4 +14,4 @@ python:
 install: pip install -r requirements.txt
 
 # command to run tests, e.g. python setup.py test
-script: py.test
+script: pytest tests/
index ba7f9b67a49622d72f07ddcd81b8161adc2b1863..179d86c29b0a58270f256cf59f7b643aba635da1 100644 (file)
@@ -74,21 +74,26 @@ Ready to contribute? Here's how to set up `cached-property` for local developmen
    
    Now you can make your changes locally.
 
-5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
+   
+5. Clean up the formatting (must be running at least Python 3.6)::
+  
+    $ pip install -U black
+    $ black .
+   
+6. When you're done making changes, check that your changes pass the tests, including testing other Python versions with tox::
 
-    $ flake8 cached-property tests
-    $ python setup.py test
+    $ pytest tests/
     $ tox
 
-   To get flake8 and tox, just pip install them into your virtualenv. 
+   To get tox, just pip install it into your virtualenv. 
 
-6. Commit your changes and push your branch to GitHub::
+7. Commit your changes and push your branch to GitHub::
 
     $ git add .
     $ git commit -m "Your detailed description of your changes."
     $ git push origin name-of-your-bugfix-or-feature
 
-7. Submit a pull request through the GitHub website.
+8. Submit a pull request through the GitHub website.
 
 Pull Request Guidelines
 -----------------------
index ac4fc1594cf642368836b59678eddd2607101e3c..f929d3eae05e6269ad8968afa1afa5c8d4112f74 100644 (file)
@@ -3,10 +3,18 @@
 History
 -------
 
-1.4.1 (2018-02-26)
+1.4.2 (2018-03-08)
+++++++++++++++++++
+
+* Really fixed tests, thanks to @pydanny
+
+1.4.1 (2018-03-08)
 ++++++++++++++++++
 
 * Added conftest.py to manifest so tests work properly off the tarball, thanks to @dotlambda
+* Ensured new asyncio tests didn't break Python 2.7 builds on Debian, thanks to @pydanny
+* Code formatting via black, thanks to @pydanny and @ambv
+
 
 1.4.0 (2018-02-25)
 ++++++++++++++++++
index 27bb40aa5c35ec05ba42bc5c15f55ac543b29ee8..badb005fbc9f8ff31775a5e43e44c906df66de08 100644 (file)
@@ -7,6 +7,10 @@ cached-property
 
 .. image:: https://img.shields.io/travis/pydanny/cached-property/master.svg
         :target: https://travis-ci.org/pydanny/cached-property
+        
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+    :target: https://github.com/ambv/black
+    :alt: Code style: black        
 
 
 A decorator for caching properties in classes.
index 53edd60de1af9a96db1335f612cfa2df168bbff1..eb9e90ff02d74be22db01da8a900824e69c5b892 100644 (file)
@@ -1,12 +1,13 @@
 # -*- coding: utf-8 -*-
 
-__author__ = 'Daniel Greenfeld'
-__email__ = 'pydanny@gmail.com'
-__version__ = '1.4.0'
-__license__ = 'BSD'
+__author__ = "Daniel Greenfeld"
+__email__ = "pydanny@gmail.com"
+__version__ = "1.4.2"
+__license__ = "BSD"
 
 from time import time
 import threading
+
 try:
     import asyncio
 except ImportError:
@@ -21,23 +22,27 @@ class cached_property(object):
     """  # noqa
 
     def __init__(self, func):
-        self.__doc__ = getattr(func, '__doc__')
+        self.__doc__ = getattr(func, "__doc__")
         self.func = func
 
     def __get__(self, obj, cls):
         if obj is None:
             return self
+
         if asyncio and asyncio.iscoroutinefunction(self.func):
             return self._wrap_in_coroutine(obj)
+
         value = obj.__dict__[self.func.__name__] = self.func(obj)
         return value
 
     def _wrap_in_coroutine(self, obj):
+
         @asyncio.coroutine
         def wrapper():
             future = asyncio.ensure_future(self.func(obj))
             obj.__dict__[self.func.__name__] = future
             return future
+
         return wrapper()
 
 
@@ -48,7 +53,7 @@ class threaded_cached_property(object):
     """
 
     def __init__(self, func):
-        self.__doc__ = getattr(func, '__doc__')
+        self.__doc__ = getattr(func, "__doc__")
         self.func = func
         self.lock = threading.RLock()
 
@@ -62,6 +67,7 @@ class threaded_cached_property(object):
             try:
                 # check if the value was computed before the lock was acquired
                 return obj_dict[name]
+
             except KeyError:
                 # if not, do the calculation and release the lock
                 return obj_dict.setdefault(name, self.func(obj))
@@ -120,6 +126,7 @@ class cached_property_with_ttl(object):
             self.__name__ = func.__name__
             self.__module__ = func.__module__
 
+
 # Aliases to make cached_property_with_ttl easier to use
 cached_property_ttl = cached_property_with_ttl
 timed_cached_property = cached_property_with_ttl
@@ -137,8 +144,8 @@ class threaded_cached_property_with_ttl(cached_property_with_ttl):
 
     def __get__(self, obj, cls):
         with self.lock:
-            return super(threaded_cached_property_with_ttl, self).__get__(obj,
-                                                                          cls)
+            return super(threaded_cached_property_with_ttl, self).__get__(obj, cls)
+
 
 # Alias to make threaded_cached_property_with_ttl easier to use
 threaded_cached_property_ttl = threaded_cached_property_with_ttl
index d68017daf8af9e021d08d8622770ef734c316887..37daf27992d4c6c9ee9293de58cfda6f5c64b537 100644 (file)
@@ -2,23 +2,19 @@
 import sys
 
 # Whether "import asyncio" works
-has_asyncio = (
-    sys.version_info[0] == 3 and sys.version_info[1] >= 4
-)
+has_asyncio = (sys.version_info[0] == 3 and sys.version_info[1] >= 4)
 
 # Whether the async and await keywords work
-has_async_await = (
-    sys.version_info[0] == 3 and sys.version_info[1] >= 5
-)
+has_async_await = (sys.version_info[0] == 3 and sys.version_info[1] >= 5)
 
 
-print('conftest.py', has_asyncio, has_async_await)
+print("conftest.py", has_asyncio, has_async_await)
 
 
 collect_ignore = []
 
 if not has_asyncio:
-    collect_ignore.append('tests/test_coroutine_cached_property.py')
+    collect_ignore.append("tests/test_coroutine_cached_property.py")
 
 if not has_async_await:
-    collect_ignore.append('tests/test_async_cached_property.py')
+    collect_ignore.append("tests/test_async_cached_property.py")
index 989a38bb6ac8889ae37581016f0811ee862abd22..02b421c95c3e9ff2bfcf13d6e16310cf140f616a 100644 (file)
@@ -3,4 +3,5 @@ coverage==4.4.2
 pytest==3.5.0
 pytest-cov==2.5.1
 freezegun==0.3.10
+twine==1.11.0
 wheel==0.31.0
index a94df4fbe4a2ff762960f16cd951721c15382844..bb1ff664ea7fca99071a3e80010a1c8ef98a7630 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -10,46 +10,49 @@ try:
 except ImportError:
     from distutils.core import setup
 
-__version__ = '1.4.0'
+__version__ = "1.4.2"
 
 
 def read(fname):
     return codecs.open(
-        os.path.join(os.path.dirname(__file__), fname), 'r', 'utf-8').read()
+        os.path.join(os.path.dirname(__file__), fname), "r", "utf-8"
+    ).read()
 
-readme = read('README.rst')
-history = read('HISTORY.rst').replace('.. :changelog:', '')
 
-if sys.argv[-1] == 'publish':
-    os.system('python setup.py sdist bdist_wheel upload')
+readme = read("README.rst")
+history = read("HISTORY.rst").replace(".. :changelog:", "")
+
+if sys.argv[-1] == "publish":
+    os.system("python setup.py sdist bdist_wheel")
+    os.system("twine upload dist/*")
     os.system("git tag -a %s -m 'version %s'" % (__version__, __version__))
     os.system("git push --tags")
     sys.exit()
 
 setup(
-    name='cached-property',
+    name="cached-property",
     version=__version__,
-    description='A decorator for caching properties in classes.',
-    long_description=readme + '\n\n' + history,
-    author='Daniel Greenfeld',
-    author_email='pydanny@gmail.com',
-    url='https://github.com/pydanny/cached-property',
-    py_modules=['cached_property'],
+    description="A decorator for caching properties in classes.",
+    long_description=readme + "\n\n" + history,
+    author="Daniel Greenfeld",
+    author_email="pydanny@gmail.com",
+    url="https://github.com/pydanny/cached-property",
+    py_modules=["cached_property"],
     include_package_data=True,
     license="BSD",
     zip_safe=False,
-    keywords='cached-property',
+    keywords="cached-property",
     classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: BSD License',
-        'Natural Language :: English',
+        "Development Status :: 5 - Production/Stable",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: BSD License",
+        "Natural Language :: English",
         "Programming Language :: Python :: 2",
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
-        'Programming Language :: Python :: 3.6',
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
+        "Programming Language :: Python :: 3.6",
     ],
 )
index 6a9fb87797b408feab9d7e9fda27c69c04675cc3..dd9e7bd87e1ea3921de3066c200db919ae62d5ae 100644 (file)
 # -*- coding: utf-8 -*-
+import asyncio
+import time
+import unittest
+from threading import Lock, Thread
+from freezegun import freeze_time
+import cached_property
+
+def unittest_run_loop(f):
+
+    def wrapper(*args, **kwargs):
+        coro = asyncio.coroutine(f)
+        future = coro(*args, **kwargs)
+        loop = asyncio.get_event_loop()
+        loop.run_until_complete(future)
+
+    return wrapper
+
+def CheckFactory(cached_property_decorator, threadsafe=False):
+    """
+    Create dynamically a Check class whose add_cached method is decorated by
+    the cached_property_decorator.
+    """
+
+    class Check(object):
+
+        def __init__(self):
+            self.control_total = 0
+            self.cached_total = 0
+            self.lock = Lock()
+
+        async def add_control(self):
+            self.control_total += 1
+            return self.control_total
+
+        @cached_property_decorator
+        async def add_cached(self):
+            if threadsafe:
+                time.sleep(1)
+                # Need to guard this since += isn't atomic.
+                with self.lock:
+                    self.cached_total += 1
+            else:
+                self.cached_total += 1
+
+            return self.cached_total
+
+        def run_threads(self, num_threads):
+            threads = []
+            for _ in range(num_threads):
 
+                def call_add_cached():
+                    loop = asyncio.new_event_loop()
+                    asyncio.set_event_loop(loop)
+                    loop.run_until_complete(self.add_cached)
 
-try:
-    import asyncio
-    import time
-    import unittest
-    from threading import Lock, Thread
-    from freezegun import freeze_time
-    import cached_property
+                thread = Thread(target=call_add_cached)
+                thread.start()
+                threads.append(thread)
+            for thread in threads:
+                thread.join()
 
+    return Check
 
-    def unittest_run_loop(f):
-        def wrapper(*args, **kwargs):
-            coro = asyncio.coroutine(f)
-            future = coro(*args, **kwargs)
-            loop = asyncio.get_event_loop()
-            loop.run_until_complete(future)
-        return wrapper
+class TestCachedProperty(unittest.TestCase):
+    """Tests for cached_property"""
 
+    cached_property_factory = cached_property.cached_property
 
-    def CheckFactory(cached_property_decorator, threadsafe=False):
+    async def assert_control(self, check, expected):
         """
-        Create dynamically a Check class whose add_cached method is decorated by
-        the cached_property_decorator.
+        Assert that both `add_control` and 'control_total` equal `expected`
         """
+        self.assertEqual(await check.add_control(), expected)
+        self.assertEqual(check.control_total, expected)
 
-        class Check(object):
+    async def assert_cached(self, check, expected):
+        """
+        Assert that both `add_cached` and 'cached_total` equal `expected`
+        """
+        print("assert_cached", check.add_cached)
+        self.assertEqual(await check.add_cached, expected)
+        self.assertEqual(check.cached_total, expected)
 
-            def __init__(self):
-                self.control_total = 0
-                self.cached_total = 0
-                self.lock = Lock()
+    @unittest_run_loop
+    async def test_cached_property(self):
+        Check = CheckFactory(self.cached_property_factory)
+        check = Check()
 
-            async def add_control(self):
-                self.control_total += 1
-                return self.control_total
+        # The control shows that we can continue to add 1
+        await self.assert_control(check, 1)
+        await self.assert_control(check, 2)
 
-            @cached_property_decorator
-            async def add_cached(self):
-                if threadsafe:
-                    time.sleep(1)
-                    # Need to guard this since += isn't atomic.
-                    with self.lock:
-                        self.cached_total += 1
-                else:
-                    self.cached_total += 1
+        # The cached version demonstrates how nothing is added after the first
+        await self.assert_cached(check, 1)
+        await self.assert_cached(check, 1)
 
-                return self.cached_total
-
-            def run_threads(self, num_threads):
-                threads = []
-                for _ in range(num_threads):
-                    def call_add_cached():
-                        loop = asyncio.new_event_loop()
-                        asyncio.set_event_loop(loop)
-                        loop.run_until_complete(self.add_cached)
-                    thread = Thread(target=call_add_cached)
-                    thread.start()
-                    threads.append(thread)
-                for thread in threads:
-                    thread.join()
-
-        return Check
-
-
-    class TestCachedProperty(unittest.TestCase):
-        """Tests for cached_property"""
-
-        cached_property_factory = cached_property.cached_property
-
-        async def assert_control(self, check, expected):
-            """
-            Assert that both `add_control` and 'control_total` equal `expected`
-            """
-            self.assertEqual(await check.add_control(), expected)
-            self.assertEqual(check.control_total, expected)
-
-        async def assert_cached(self, check, expected):
-            """
-            Assert that both `add_cached` and 'cached_total` equal `expected`
-            """
-            print('assert_cached', check.add_cached)
-            self.assertEqual(await check.add_cached, expected)
-            self.assertEqual(check.cached_total, expected)
-
-        @unittest_run_loop
-        async def test_cached_property(self):
-            Check = CheckFactory(self.cached_property_factory)
-            check = Check()
-
-            # The control shows that we can continue to add 1
-            await self.assert_control(check, 1)
-            await self.assert_control(check, 2)
-
-            # The cached version demonstrates how nothing is added after the first
-            await self.assert_cached(check, 1)
+        # The cache does not expire
+        with freeze_time("9999-01-01"):
             await self.assert_cached(check, 1)
 
-            # The cache does not expire
-            with freeze_time("9999-01-01"):
-                await self.assert_cached(check, 1)
-
-            # Typically descriptors return themselves if accessed though the class
-            # rather than through an instance.
-            self.assertTrue(isinstance(Check.add_cached,
-                                       self.cached_property_factory))
+        # Typically descriptors return themselves if accessed though the class
+        # rather than through an instance.
+        self.assertTrue(isinstance(Check.add_cached, self.cached_property_factory))
 
-        @unittest_run_loop
-        async def test_reset_cached_property(self):
-            Check = CheckFactory(self.cached_property_factory)
-            check = Check()
+    @unittest_run_loop
+    async def test_reset_cached_property(self):
+        Check = CheckFactory(self.cached_property_factory)
+        check = Check()
 
-            # Run standard cache assertion
-            await self.assert_cached(check, 1)
-            await self.assert_cached(check, 1)
+        # Run standard cache assertion
+        await self.assert_cached(check, 1)
+        await self.assert_cached(check, 1)
 
-            # Clear the cache
-            del check.add_cached
+        # Clear the cache
+        del check.add_cached
 
-            # Value is cached again after the next access
-            await self.assert_cached(check, 2)
-            await self.assert_cached(check, 2)
+        # Value is cached again after the next access
+        await self.assert_cached(check, 2)
+        await self.assert_cached(check, 2)
 
-        @unittest_run_loop
-        async def test_none_cached_property(self):
-            class Check(object):
+    @unittest_run_loop
+    async def test_none_cached_property(self):
 
-                def __init__(self):
-                    self.cached_total = None
+        class Check(object):
 
-                @self.cached_property_factory
-                async def add_cached(self):
-                    return self.cached_total
+            def __init__(self):
+                self.cached_total = None
 
-            await self.assert_cached(Check(), None)
+            @self.cached_property_factory
+            async def add_cached(self):
+                return self.cached_total
 
-        
-except ImportError:
-    pass  # Running older version of Python that doesn't support asyncio
-        
+        await self.assert_cached(Check(), None)  
\ No newline at end of file
index 1e0e68a577461e66d4d4cd6904f7b989eac700a9..5d8ea92d854e6ede5886b9896dfb844f10d2bebd 100644 (file)
@@ -87,8 +87,7 @@ class TestCachedProperty(unittest.TestCase):
 
         # Typically descriptors return themselves if accessed though the class
         # rather than through an instance.
-        self.assertTrue(isinstance(Check.add_cached,
-                                   self.cached_property_factory))
+        self.assertTrue(isinstance(Check.add_cached, self.cached_property_factory))
 
     def test_reset_cached_property(self):
         Check = CheckFactory(self.cached_property_factory)
@@ -106,6 +105,7 @@ class TestCachedProperty(unittest.TestCase):
         self.assert_cached(check, 2)
 
     def test_none_cached_property(self):
+
         class Check(object):
 
             def __init__(self):
@@ -120,8 +120,8 @@ class TestCachedProperty(unittest.TestCase):
     def test_set_cached_property(self):
         Check = CheckFactory(self.cached_property_factory)
         check = Check()
-        check.add_cached = 'foo'
-        self.assertEqual(check.add_cached, 'foo')
+        check.add_cached = "foo"
+        self.assertEqual(check.add_cached, "foo")
         self.assertEqual(check.cached_total, 0)
 
     def test_threads(self):
@@ -192,8 +192,7 @@ class TestCachedPropertyWithTTL(TestCachedProperty):
         self.assert_cached(check, 2)
 
     def test_threads_ttl_expiry(self):
-        Check = CheckFactory(self.cached_property_factory(ttl=100000),
-                             threadsafe=True)
+        Check = CheckFactory(self.cached_property_factory(ttl=100000), threadsafe=True)
         check = Check()
         num_threads = 5
 
@@ -213,15 +212,15 @@ class TestCachedPropertyWithTTL(TestCachedProperty):
         self.assert_cached(check, 2 * num_threads)
 
 
-class TestThreadedCachedPropertyWithTTL(TestThreadedCachedProperty,
-                                        TestCachedPropertyWithTTL):
+class TestThreadedCachedPropertyWithTTL(
+    TestThreadedCachedProperty, TestCachedPropertyWithTTL
+):
     """Tests for threaded_cached_property_with_ttl"""
 
     cached_property_factory = cached_property.threaded_cached_property_with_ttl
 
     def test_threads_ttl_expiry(self):
-        Check = CheckFactory(self.cached_property_factory(ttl=100000),
-                             threadsafe=True)
+        Check = CheckFactory(self.cached_property_factory(ttl=100000), threadsafe=True)
         check = Check()
         num_threads = 5
 
index ede9baf00fbf123089c6f035f275e33c33a06b8f..30723cf8f298fcde27e201ef0aedded0d7342956 100644 (file)
@@ -13,11 +13,13 @@ import cached_property
 
 
 def unittest_run_loop(f):
+
     def wrapper(*args, **kwargs):
         coro = asyncio.coroutine(f)
         future = coro(*args, **kwargs)
         loop = asyncio.get_event_loop()
         loop.run_until_complete(future)
+
     return wrapper
 
 
@@ -66,7 +68,7 @@ class TestCachedProperty(unittest.TestCase):
         """
         Assert that both `add_cached` and 'cached_total` equal `expected`
         """
-        print('assert_cached', check.add_cached)
+        print("assert_cached", check.add_cached)
         value = yield from check.add_cached
         self.assertEqual(value, expected)
         self.assertEqual(check.cached_total, expected)
@@ -91,8 +93,7 @@ class TestCachedProperty(unittest.TestCase):
 
         # Typically descriptors return themselves if accessed though the class
         # rather than through an instance.
-        self.assertTrue(isinstance(Check.add_cached,
-                                   self.cached_property_factory))
+        self.assertTrue(isinstance(Check.add_cached, self.cached_property_factory))
 
     @unittest_run_loop
     @asyncio.coroutine
@@ -114,6 +115,7 @@ class TestCachedProperty(unittest.TestCase):
     @unittest_run_loop
     @asyncio.coroutine
     def test_none_cached_property(self):
+
         class Check(object):
 
             def __init__(self):
diff --git a/tox.ini b/tox.ini
index 2d69b26e5e43caf1fc2e4f371e6df395e0907a2c..4f94c9bdc001952ca073b2e2258ac775ff2b9af1 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@ envlist = py27, py33, py34, py35, py36
 [testenv]
 setenv =
     PYTHONPATH = {toxinidir}:{toxinidir}/cached-property
-commands = py.test
+commands = pytest tests/
 deps =
     pytest
     freezegun