[Python-modules-commits] [backports.functools-lru-cache] 01/09: import backports.functools-lru-cache_1.3.orig.tar.gz

Sandro Tosi morph at moszumanska.debian.org
Thu Dec 15 12:56:03 UTC 2016


This is an automated email from the git hooks/post-receive script.

morph pushed a commit to branch master
in repository backports.functools-lru-cache.

commit 91f723b5a925add57f6c4520cc437cdc8fc2d8f7
Author: Sandro Tosi <morph at debian.org>
Date:   Thu Dec 15 07:24:01 2016 -0500

    import backports.functools-lru-cache_1.3.orig.tar.gz
---
 .gitignore                       |  64 ++++++++++++++
 .travis.yml                      |  24 +++++
 CHANGES.rst                      |  17 ++++
 PKG-INFO                         |  42 +++++++++
 README.rst                       |  26 ++++++
 backports/__init__.py            |   1 +
 backports/functools_lru_cache.py | 184 +++++++++++++++++++++++++++++++++++++++
 docs/conf.py                     |  39 +++++++++
 docs/history.rst                 |   8 ++
 docs/index.rst                   |  22 +++++
 pytest.ini                       |   4 +
 setup.cfg                        |  15 ++++
 setup.py                         |  51 +++++++++++
 tests/requirements.txt           |   1 +
 tests/test_lru_cache.py          |  11 +++
 tox.ini                          |   6 ++
 16 files changed, 515 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..80b3e15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,64 @@
+
+# Created by https://www.gitignore.io/api/python
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a7eeab9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,24 @@
+sudo: false
+language: python
+python:
+- 2.6
+- 2.7
+- 3.5
+install:
+- pip install tox
+script:
+- tox
+branches:
+  except:
+  - skeleton
+deploy:
+  provider: pypi
+  server: https://upload.pypi.org/legacy/
+  on:
+    tags: true
+    all_branches: true
+    python: 3.5
+  user: jaraco
+  distributions: dists
+  password:
+    secure: mJUt/9xGGfOMjAug7PEJojli2VgQyoCKx88amgK595lfdK/cAmTGi/na3Hw3Kt/7bfNjGCWyYzoXZ1VAhCDiiG8mOnWszTSNoeQSS4NCTkR7f1oUEo7izLrsGpEs8aveXY3XlqW5VTnssaL526ju5vIXDPKvhqvLrYkd7mP62HcL3rbSJM72D54OUVVX0gEKf4swgwjQe6xNQyRQpq/QcIKXxqgKF3/qIbnJQWGv7tDuxaWLghh2gx3oBNZVmQKBWfokwjp+PWV7zqIrE2o5sZ5Jkh+kt5+UOVDyMh/3Fd4s2G6ZD6asDRA5QBQxo/QtF2fQsi8heE4VgChRrnKzYXAZN1CSEj9i7BgBq2nbRod5WqlCR44zC44A4qS+D5ZlZVdmamZY9ni2/vZ6xMxl4m8Yk30xBHIoo+huJjLimnOETp9YTArMlebfPetCE6C6Tu3rmVoftiW2npjaBBxDCglSdRmluf+f [...]
diff --git a/CHANGES.rst b/CHANGES.rst
new file mode 100644
index 0000000..cfc1a72
--- /dev/null
+++ b/CHANGES.rst
@@ -0,0 +1,17 @@
+1.3
+===
+
+Tagged commits are automatically released following passing
+tests.
+
+1.2
+===
+
+Issue #5: Added a minimal test suite.
+
+1.1
+===
+
+Moved hosting to Github.
+Library uses setuptools_scm for version tagging.
+Added license declaration.
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..2c2c042
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,42 @@
+Metadata-Version: 1.1
+Name: backports.functools_lru_cache
+Version: 1.3
+Summary: backports.functools_lru_cache
+Home-page: https://github.com/jaraco/backports.functools_lru_cache
+Author: Jason R. Coombs
+Author-email: jaraco at jaraco.com
+License: UNKNOWN
+Description: .. image:: https://img.shields.io/pypi/v/backports.functools_lru_cache.svg
+           :target: https://pypi.org/project/backports.functools_lru_cache
+        
+        .. image:: https://img.shields.io/pypi/pyversions/backports.functools_lru_cache.svg
+        
+        .. image:: https://img.shields.io/pypi/dm/backports.functools_lru_cache.svg
+        
+        .. image:: https://img.shields.io/travis/jaraco/backports.functools_lru_cache/master.svg
+           :target: http://travis-ci.org/jaraco/backports.functools_lru_cache
+        
+        License is indicated in the project metadata (typically one or more
+        of the Trove classifiers). For more details, see `this explanation
+        <https://github.com/jaraco/skeleton/issues/1>`_.
+        
+        Backport of functools.lru_cache from Python 3.3 as published at `ActiveState
+        <http://code.activestate.com/recipes/578078/>`_.
+        
+        Usage
+        -----
+        
+        Consider using this technique for importing the 'lru_cache' function::
+        
+            try:
+                from functools import lru_cache
+            except ImportError:
+                from backports.functools_lru_cache import lru_cache
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..8806b9f
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,26 @@
+.. image:: https://img.shields.io/pypi/v/backports.functools_lru_cache.svg
+   :target: https://pypi.org/project/backports.functools_lru_cache
+
+.. image:: https://img.shields.io/pypi/pyversions/backports.functools_lru_cache.svg
+
+.. image:: https://img.shields.io/pypi/dm/backports.functools_lru_cache.svg
+
+.. image:: https://img.shields.io/travis/jaraco/backports.functools_lru_cache/master.svg
+   :target: http://travis-ci.org/jaraco/backports.functools_lru_cache
+
+License is indicated in the project metadata (typically one or more
+of the Trove classifiers). For more details, see `this explanation
+<https://github.com/jaraco/skeleton/issues/1>`_.
+
+Backport of functools.lru_cache from Python 3.3 as published at `ActiveState
+<http://code.activestate.com/recipes/578078/>`_.
+
+Usage
+-----
+
+Consider using this technique for importing the 'lru_cache' function::
+
+    try:
+        from functools import lru_cache
+    except ImportError:
+        from backports.functools_lru_cache import lru_cache
diff --git a/backports/__init__.py b/backports/__init__.py
new file mode 100644
index 0000000..5284146
--- /dev/null
+++ b/backports/__init__.py
@@ -0,0 +1 @@
+__import__("pkg_resources").declare_namespace(__name__)
diff --git a/backports/functools_lru_cache.py b/backports/functools_lru_cache.py
new file mode 100644
index 0000000..707c6c7
--- /dev/null
+++ b/backports/functools_lru_cache.py
@@ -0,0 +1,184 @@
+from __future__ import absolute_import
+
+import functools
+from collections import namedtuple
+from threading import RLock
+
+_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
+
+
+ at functools.wraps(functools.update_wrapper)
+def update_wrapper(wrapper,
+                   wrapped,
+                   assigned = functools.WRAPPER_ASSIGNMENTS,
+                   updated = functools.WRAPPER_UPDATES):
+    """
+    Patch two bugs in functools.update_wrapper.
+    """
+    # workaround for http://bugs.python.org/issue3445
+    assigned = tuple(attr for attr in assigned if hasattr(wrapped, attr))
+    wrapper = functools.update_wrapper(wrapper, wrapped, assigned, updated)
+    # workaround for https://bugs.python.org/issue17482
+    wrapper.__wrapped__ = wrapped
+    return wrapper
+
+
+class _HashedSeq(list):
+    __slots__ = 'hashvalue'
+
+    def __init__(self, tup, hash=hash):
+        self[:] = tup
+        self.hashvalue = hash(tup)
+
+    def __hash__(self):
+        return self.hashvalue
+
+
+def _make_key(args, kwds, typed,
+              kwd_mark=(object(),),
+              fasttypes=set([int, str, frozenset, type(None)]),
+              sorted=sorted, tuple=tuple, type=type, len=len):
+    'Make a cache key from optionally typed positional and keyword arguments'
+    key = args
+    if kwds:
+        sorted_items = sorted(kwds.items())
+        key += kwd_mark
+        for item in sorted_items:
+            key += item
+    if typed:
+        key += tuple(type(v) for v in args)
+        if kwds:
+            key += tuple(type(v) for k, v in sorted_items)
+    elif len(key) == 1 and type(key[0]) in fasttypes:
+        return key[0]
+    return _HashedSeq(key)
+
+
+def lru_cache(maxsize=100, typed=False):
+    """Least-recently-used cache decorator.
+
+    If *maxsize* is set to None, the LRU features are disabled and the cache
+    can grow without bound.
+
+    If *typed* is True, arguments of different types will be cached separately.
+    For example, f(3.0) and f(3) will be treated as distinct calls with
+    distinct results.
+
+    Arguments to the cached function must be hashable.
+
+    View the cache statistics named tuple (hits, misses, maxsize, currsize) with
+    f.cache_info().  Clear the cache and statistics with f.cache_clear().
+    Access the underlying function with f.__wrapped__.
+
+    See:  http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
+
+    """
+
+    # Users should only access the lru_cache through its public API:
+    #       cache_info, cache_clear, and f.__wrapped__
+    # The internals of the lru_cache are encapsulated for thread safety and
+    # to allow the implementation to change (including a possible C version).
+
+    def decorating_function(user_function):
+
+        cache = dict()
+        stats = [0, 0]                  # make statistics updateable non-locally
+        HITS, MISSES = 0, 1             # names for the stats fields
+        make_key = _make_key
+        cache_get = cache.get           # bound method to lookup key or return None
+        _len = len                      # localize the global len() function
+        lock = RLock()                  # because linkedlist updates aren't threadsafe
+        root = []                       # root of the circular doubly linked list
+        root[:] = [root, root, None, None]      # initialize by pointing to self
+        nonlocal_root = [root]                  # make updateable non-locally
+        PREV, NEXT, KEY, RESULT = 0, 1, 2, 3    # names for the link fields
+
+        if maxsize == 0:
+
+            def wrapper(*args, **kwds):
+                # no caching, just do a statistics update after a successful call
+                result = user_function(*args, **kwds)
+                stats[MISSES] += 1
+                return result
+
+        elif maxsize is None:
+
+            def wrapper(*args, **kwds):
+                # simple caching without ordering or size limit
+                key = make_key(args, kwds, typed)
+                result = cache_get(key, root)   # root used here as a unique not-found sentinel
+                if result is not root:
+                    stats[HITS] += 1
+                    return result
+                result = user_function(*args, **kwds)
+                cache[key] = result
+                stats[MISSES] += 1
+                return result
+
+        else:
+
+            def wrapper(*args, **kwds):
+                # size limited caching that tracks accesses by recency
+                key = make_key(args, kwds, typed) if kwds or typed else args
+                with lock:
+                    link = cache_get(key)
+                    if link is not None:
+                        # record recent use of the key by moving it to the front of the list
+                        root, = nonlocal_root
+                        link_prev, link_next, key, result = link
+                        link_prev[NEXT] = link_next
+                        link_next[PREV] = link_prev
+                        last = root[PREV]
+                        last[NEXT] = root[PREV] = link
+                        link[PREV] = last
+                        link[NEXT] = root
+                        stats[HITS] += 1
+                        return result
+                result = user_function(*args, **kwds)
+                with lock:
+                    root, = nonlocal_root
+                    if key in cache:
+                        # getting here means that this same key was added to the
+                        # cache while the lock was released.  since the link
+                        # update is already done, we need only return the
+                        # computed result and update the count of misses.
+                        pass
+                    elif _len(cache) >= maxsize:
+                        # use the old root to store the new key and result
+                        oldroot = root
+                        oldroot[KEY] = key
+                        oldroot[RESULT] = result
+                        # empty the oldest link and make it the new root
+                        root = nonlocal_root[0] = oldroot[NEXT]
+                        oldkey = root[KEY]
+                        root[KEY] = root[RESULT] = None
+                        # now update the cache dictionary for the new links
+                        del cache[oldkey]
+                        cache[key] = oldroot
+                    else:
+                        # put result in a new link at the front of the list
+                        last = root[PREV]
+                        link = [last, root, key, result]
+                        last[NEXT] = root[PREV] = cache[key] = link
+                    stats[MISSES] += 1
+                return result
+
+        def cache_info():
+            """Report cache statistics"""
+            with lock:
+                return _CacheInfo(stats[HITS], stats[MISSES], maxsize, len(cache))
+
+        def cache_clear():
+            """Clear the cache and cache statistics"""
+            with lock:
+                cache.clear()
+                root = nonlocal_root[0]
+                root[:] = [root, root, None, None]
+                stats[:] = [0, 0]
+
+        wrapper.__wrapped__ = user_function
+        wrapper.cache_info = cache_info
+        wrapper.cache_clear = cache_clear
+        return update_wrapper(wrapper, user_function)
+
+    return decorating_function
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..8ec74ba
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import pkg_resources
+
+extensions = [
+    'sphinx.ext.autodoc',
+    'rst.linker',
+]
+
+# General information about the project.
+project = 'backports.functools_lru_cache'
+copyright = '2015-2016 Jason R. Coombs'
+
+# The short X.Y version.
+version = pkg_resources.require(project)[0].version
+# The full version, including alpha/beta/rc tags.
+release = version
+
+master_doc = 'index'
+
+link_files = {
+	'CHANGES.rst': dict(
+		using=dict(
+			GH='https://github.com',
+			project=project,
+		),
+		replace=[
+			dict(
+				pattern=r"(Issue )?#(?P<issue>\d+)",
+				url='{GH}/jaraco/{project}/issues/{issue}',
+			),
+			dict(
+				pattern=r"^(?m)((?P<scm_version>v?\d+(\.\d+){1,2}))\n[-=]+\n",
+				with_scm="{text}\n{rev[timestamp]:%d %b %Y}\n",
+			),
+		],
+	),
+}
diff --git a/docs/history.rst b/docs/history.rst
new file mode 100644
index 0000000..8e21750
--- /dev/null
+++ b/docs/history.rst
@@ -0,0 +1,8 @@
+:tocdepth: 2
+
+.. _changes:
+
+History
+*******
+
+.. include:: ../CHANGES (links).rst
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..b563b35
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,22 @@
+Welcome to backports.functools_lru_cache documentation!
+============================================
+
+.. toctree::
+   :maxdepth: 1
+
+   history
+
+
+.. automodule:: backports.functools_lru_cache
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..56a8774
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,4 @@
+[pytest]
+norecursedirs=dist build .tox
+addopts=--doctest-modules
+doctest_optionflags=ALLOW_UNICODE ELLIPSIS
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..c1794d2
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,15 @@
+[aliases]
+release = dists upload
+dists = clean --all sdist bdist_wheel
+
+[wheel]
+universal = 1
+
+[upload]
+repository = https://upload.pypi.org/legacy/
+
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..4568df7
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+# Project skeleton maintained at https://github.com/jaraco/skeleton
+
+import io
+import sys
+
+import setuptools
+
+with io.open('README.rst', encoding='utf-8') as readme:
+	long_description = readme.read()
+
+needs_wheel = set(['release', 'bdist_wheel', 'dists']).intersection(sys.argv)
+wheel = ['wheel'] if needs_wheel else []
+
+name = 'backports.functools_lru_cache'
+description = ''
+
+setup_params = dict(
+	name=name,
+	use_scm_version=True,
+	author="Raymond Hettinger",
+	author_email="raymond.hettinger at gmail.com",
+	maintainer="Jason R. Coombs",
+	maintainer_email="jaraco at jaraco.com",
+	description=description or name,
+	long_description=long_description,
+	url="https://github.com/jaraco/" + name,
+	packages=setuptools.find_packages(),
+	include_package_data=True,
+	namespace_packages=name.split('.')[:-1],
+	install_requires=[
+	],
+	extras_require={
+	},
+	setup_requires=[
+		'setuptools_scm>=1.9',
+	] + wheel,
+	classifiers=[
+		"Development Status :: 5 - Production/Stable",
+		"Intended Audience :: Developers",
+		"License :: OSI Approved :: MIT License",
+		"Programming Language :: Python :: 2.6",
+		"Programming Language :: Python :: 2.7",
+		"Programming Language :: Python :: 3",
+	],
+	entry_points={
+	},
+)
+if __name__ == '__main__':
+	setuptools.setup(**setup_params)
diff --git a/tests/requirements.txt b/tests/requirements.txt
new file mode 100644
index 0000000..70bc02f
--- /dev/null
+++ b/tests/requirements.txt
@@ -0,0 +1 @@
+pytest >= 2.8
diff --git a/tests/test_lru_cache.py b/tests/test_lru_cache.py
new file mode 100644
index 0000000..3e84313
--- /dev/null
+++ b/tests/test_lru_cache.py
@@ -0,0 +1,11 @@
+import random
+
+from backports.functools_lru_cache import lru_cache
+
+
+def test_invocation():
+	@lru_cache()
+	def func():
+		return random.random()
+
+	assert func() == func()
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..564f205
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,6 @@
+[testenv]
+deps =
+	-rtests/requirements.txt
+
+commands = py.test
+usedevelop = True

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/backports.functools-lru-cache.git



More information about the Python-modules-commits mailing list