singledispatch-3.4.0.2/ 0000755 0000767 0000024 00000000000 12164513654 014740 5 ustar ambv staff 0000000 0000000 singledispatch-3.4.0.2/MANIFEST.in 0000644 0000767 0000024 00000000023 12150225563 016463 0 ustar ambv staff 0000000 0000000 include README.rst
singledispatch-3.4.0.2/PKG-INFO 0000644 0000767 0000024 00000022373 12164513654 016044 0 ustar ambv staff 0000000 0000000 Metadata-Version: 1.1
Name: singledispatch
Version: 3.4.0.2
Summary: This library brings functools.singledispatch from Python 3.4 to Python 2.6-3.3.
Home-page: http://docs.python.org/3/library/functools.html#functools.singledispatch
Author: Łukasz Langa
Author-email: lukasz@langa.pl
License: MIT
Description: ==============
singledispatch
==============
`PEP 443 `_ proposed to expose
a mechanism in the ``functools`` standard library module in Python 3.4
that provides a simple form of generic programming known as
single-dispatch generic functions.
This library is a backport of this functionality to Python 2.6 - 3.3.
To define a generic function, decorate it with the ``@singledispatch``
decorator. Note that the dispatch happens on the type of the first
argument, create your function accordingly::
>>> from singledispatch import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
To add overloaded implementations to the function, use the
``register()`` attribute of the generic function. It is a decorator,
taking a type parameter and decorating a function implementing the
operation for that type::
>>> @fun.register(int)
... def _(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)
...
>>> @fun.register(list)
... def _(arg, verbose=False):
... if verbose:
... print("Enumerate this:")
... for i, elem in enumerate(arg):
... print(i, elem)
To enable registering lambdas and pre-existing functions, the
``register()`` attribute can be used in a functional form::
>>> def nothing(arg, verbose=False):
... print("Nothing.")
...
>>> fun.register(type(None), nothing)
The ``register()`` attribute returns the undecorated function which
enables decorator stacking, pickling, as well as creating unit tests for
each variant independently::
>>> @fun.register(float)
... @fun.register(Decimal)
... def fun_num(arg, verbose=False):
... if verbose:
... print("Half of your number:", end=" ")
... print(arg / 2)
...
>>> fun_num is fun
False
When called, the generic function dispatches on the type of the first
argument::
>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615
Where there is no registered implementation for a specific type, its
method resolution order is used to find a more generic implementation.
The original function decorated with ``@singledispatch`` is registered
for the base ``object`` type, which means it is used if no better
implementation is found.
To check which implementation will the generic function choose for
a given type, use the ``dispatch()`` attribute::
>>> fun.dispatch(float)
>>> fun.dispatch(dict) # note: default implementation
To access all registered implementations, use the read-only ``registry``
attribute::
>>> fun.registry.keys()
dict_keys([, , ,
, ,
])
>>> fun.registry[float]
>>> fun.registry[object]
The vanilla documentation is available at
http://docs.python.org/3/library/functools.html#functools.singledispatch.
Versioning
----------
This backport is intended to keep 100% compatibility with the vanilla
release in Python 3.4+. To help maintaining a version you want and
expect, a versioning scheme is used where:
* the first three numbers indicate the version of Python 3.x from which the
backport is done
* a backport release number is provided after the last dot
For example, ``3.4.0.0`` is the **first** release of ``singledispatch``
compatible with the library found in Python **3.4.0**.
A single exception from the 100% compatibility principle is that bugs
fixed before releasing another minor Python 3.x.y version **will be
included** in the backport releases done in the mean time. This rule
applies to bugs only.
Maintenance
-----------
This backport is maintained on BitBucket by Łukasz Langa, one of the
members of the core CPython team:
* `singledispatch Mercurial repository `_
* `singledispatch issue tracker `_
Change Log
----------
3.4.0.2
~~~~~~~
Updated to the reference implementation as of 02-July-2013.
* more predictable dispatch order when abstract base classes are in use:
abstract base classes are now inserted into the MRO of the argument's
class where their functionality is introduced, i.e. issubclass(cls,
abc) returns True for the class itself but returns False for all its
direct base classes. Implicit ABCs for a given class (either
registered or inferred from the presence of a special method like
__len__) are inserted directly after the last ABC explicitly listed in
the MRO of said class. This also means there are less "ambiguous
dispatch" exceptions raised.
* better test coverage and improved docstrings
3.4.0.1
~~~~~~~
Updated to the reference implementation as of 31-May-2013.
* better performance
* fixed a corner case with PEP 435 enums
* calls to `dispatch()` also cached
* dispatching algorithm now now a module-level routine called `_find_impl()`
with a simplified implementation and proper documentation
* `dispatch()` now handles all caching-related activities
* terminology more consistent: "overload" -> "implementation"
3.4.0.0
~~~~~~~
* the first public release compatible with 3.4.0
Conversion Process
------------------
This section is technical and should bother you only if you are
wondering how this backport is produced. If the implementation details
of this backport are not important for you, feel free to ignore the
following content.
``singledispatch`` is converted using `six
`_ so that a single codebase can be
used for all compatible Python versions. Because a fully automatic
conversion was not doable, I took the following branching approach:
* the ``upstream`` branch holds unchanged files synchronized from the
upstream CPython repository. The synchronization is currently done by
manually copying the required code parts and stating from which
CPython changeset they come from. The tests should pass on Python 3.4
on this branch.
* the ``default`` branch holds the manually translated version and this
is where all tests are run for all supported Python versions using
Tox.
Keywords: single dispatch generic functions singledispatch genericfunctions decorator backport
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
singledispatch-3.4.0.2/README.rst 0000644 0000767 0000024 00000015005 12164511757 016432 0 ustar ambv staff 0000000 0000000 ==============
singledispatch
==============
`PEP 443 `_ proposed to expose
a mechanism in the ``functools`` standard library module in Python 3.4
that provides a simple form of generic programming known as
single-dispatch generic functions.
This library is a backport of this functionality to Python 2.6 - 3.3.
To define a generic function, decorate it with the ``@singledispatch``
decorator. Note that the dispatch happens on the type of the first
argument, create your function accordingly::
>>> from singledispatch import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
To add overloaded implementations to the function, use the
``register()`` attribute of the generic function. It is a decorator,
taking a type parameter and decorating a function implementing the
operation for that type::
>>> @fun.register(int)
... def _(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)
...
>>> @fun.register(list)
... def _(arg, verbose=False):
... if verbose:
... print("Enumerate this:")
... for i, elem in enumerate(arg):
... print(i, elem)
To enable registering lambdas and pre-existing functions, the
``register()`` attribute can be used in a functional form::
>>> def nothing(arg, verbose=False):
... print("Nothing.")
...
>>> fun.register(type(None), nothing)
The ``register()`` attribute returns the undecorated function which
enables decorator stacking, pickling, as well as creating unit tests for
each variant independently::
>>> @fun.register(float)
... @fun.register(Decimal)
... def fun_num(arg, verbose=False):
... if verbose:
... print("Half of your number:", end=" ")
... print(arg / 2)
...
>>> fun_num is fun
False
When called, the generic function dispatches on the type of the first
argument::
>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615
Where there is no registered implementation for a specific type, its
method resolution order is used to find a more generic implementation.
The original function decorated with ``@singledispatch`` is registered
for the base ``object`` type, which means it is used if no better
implementation is found.
To check which implementation will the generic function choose for
a given type, use the ``dispatch()`` attribute::
>>> fun.dispatch(float)
>>> fun.dispatch(dict) # note: default implementation
To access all registered implementations, use the read-only ``registry``
attribute::
>>> fun.registry.keys()
dict_keys([, , ,
, ,
])
>>> fun.registry[float]
>>> fun.registry[object]
The vanilla documentation is available at
http://docs.python.org/3/library/functools.html#functools.singledispatch.
Versioning
----------
This backport is intended to keep 100% compatibility with the vanilla
release in Python 3.4+. To help maintaining a version you want and
expect, a versioning scheme is used where:
* the first three numbers indicate the version of Python 3.x from which the
backport is done
* a backport release number is provided after the last dot
For example, ``3.4.0.0`` is the **first** release of ``singledispatch``
compatible with the library found in Python **3.4.0**.
A single exception from the 100% compatibility principle is that bugs
fixed before releasing another minor Python 3.x.y version **will be
included** in the backport releases done in the mean time. This rule
applies to bugs only.
Maintenance
-----------
This backport is maintained on BitBucket by Łukasz Langa, one of the
members of the core CPython team:
* `singledispatch Mercurial repository `_
* `singledispatch issue tracker `_
Change Log
----------
3.4.0.2
~~~~~~~
Updated to the reference implementation as of 02-July-2013.
* more predictable dispatch order when abstract base classes are in use:
abstract base classes are now inserted into the MRO of the argument's
class where their functionality is introduced, i.e. issubclass(cls,
abc) returns True for the class itself but returns False for all its
direct base classes. Implicit ABCs for a given class (either
registered or inferred from the presence of a special method like
__len__) are inserted directly after the last ABC explicitly listed in
the MRO of said class. This also means there are less "ambiguous
dispatch" exceptions raised.
* better test coverage and improved docstrings
3.4.0.1
~~~~~~~
Updated to the reference implementation as of 31-May-2013.
* better performance
* fixed a corner case with PEP 435 enums
* calls to `dispatch()` also cached
* dispatching algorithm now now a module-level routine called `_find_impl()`
with a simplified implementation and proper documentation
* `dispatch()` now handles all caching-related activities
* terminology more consistent: "overload" -> "implementation"
3.4.0.0
~~~~~~~
* the first public release compatible with 3.4.0
Conversion Process
------------------
This section is technical and should bother you only if you are
wondering how this backport is produced. If the implementation details
of this backport are not important for you, feel free to ignore the
following content.
``singledispatch`` is converted using `six
`_ so that a single codebase can be
used for all compatible Python versions. Because a fully automatic
conversion was not doable, I took the following branching approach:
* the ``upstream`` branch holds unchanged files synchronized from the
upstream CPython repository. The synchronization is currently done by
manually copying the required code parts and stating from which
CPython changeset they come from. The tests should pass on Python 3.4
on this branch.
* the ``default`` branch holds the manually translated version and this
is where all tests are run for all supported Python versions using
Tox.
singledispatch-3.4.0.2/setup.cfg 0000644 0000767 0000024 00000000073 12164513654 016561 0 ustar ambv staff 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
singledispatch-3.4.0.2/setup.py 0000644 0000767 0000024 00000006033 12164507716 016456 0 ustar ambv staff 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
"""This library brings functools.singledispatch from Python 3.4 to Python 2.6-3.3."""
# Copyright (C) 2013 by Łukasz Langa
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
import sys
import codecs
from setuptools import setup, find_packages
PY3 = sys.version_info[0] == 3
if not PY3:
reload(sys)
sys.setdefaultencoding('utf8')
with codecs.open(
os.path.join(os.path.dirname(__file__), 'README.rst'), 'r', 'utf8',
) as ld_file:
long_description = ld_file.read()
# We let it die a horrible tracebacking death if reading the file fails.
# We couldn't sensibly recover anyway: we need the long description.
install_requires = ['six']
if sys.version_info[:2] < (2, 7):
install_requires.append('ordereddict')
setup (
name = 'singledispatch',
version = '3.4.0.2',
author = 'Łukasz Langa',
author_email = 'lukasz@langa.pl',
description = __doc__,
long_description = long_description,
url = 'http://docs.python.org/3/library/functools.html'
'#functools.singledispatch',
keywords = 'single dispatch generic functions singledispatch '
'genericfunctions decorator backport',
platforms = ['any'],
license = 'MIT',
py_modules = ('singledispatch', 'singledispatch_helpers'),
zip_safe = True,
install_requires = install_requires,
classifiers = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
]
)
singledispatch-3.4.0.2/singledispatch.egg-info/ 0000755 0000767 0000024 00000000000 12164513654 021433 5 ustar ambv staff 0000000 0000000 singledispatch-3.4.0.2/singledispatch.egg-info/dependency_links.txt 0000644 0000767 0000024 00000000001 12164513654 025501 0 ustar ambv staff 0000000 0000000
singledispatch-3.4.0.2/singledispatch.egg-info/PKG-INFO 0000644 0000767 0000024 00000022373 12164513654 022537 0 ustar ambv staff 0000000 0000000 Metadata-Version: 1.1
Name: singledispatch
Version: 3.4.0.2
Summary: This library brings functools.singledispatch from Python 3.4 to Python 2.6-3.3.
Home-page: http://docs.python.org/3/library/functools.html#functools.singledispatch
Author: Łukasz Langa
Author-email: lukasz@langa.pl
License: MIT
Description: ==============
singledispatch
==============
`PEP 443 `_ proposed to expose
a mechanism in the ``functools`` standard library module in Python 3.4
that provides a simple form of generic programming known as
single-dispatch generic functions.
This library is a backport of this functionality to Python 2.6 - 3.3.
To define a generic function, decorate it with the ``@singledispatch``
decorator. Note that the dispatch happens on the type of the first
argument, create your function accordingly::
>>> from singledispatch import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
To add overloaded implementations to the function, use the
``register()`` attribute of the generic function. It is a decorator,
taking a type parameter and decorating a function implementing the
operation for that type::
>>> @fun.register(int)
... def _(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)
...
>>> @fun.register(list)
... def _(arg, verbose=False):
... if verbose:
... print("Enumerate this:")
... for i, elem in enumerate(arg):
... print(i, elem)
To enable registering lambdas and pre-existing functions, the
``register()`` attribute can be used in a functional form::
>>> def nothing(arg, verbose=False):
... print("Nothing.")
...
>>> fun.register(type(None), nothing)
The ``register()`` attribute returns the undecorated function which
enables decorator stacking, pickling, as well as creating unit tests for
each variant independently::
>>> @fun.register(float)
... @fun.register(Decimal)
... def fun_num(arg, verbose=False):
... if verbose:
... print("Half of your number:", end=" ")
... print(arg / 2)
...
>>> fun_num is fun
False
When called, the generic function dispatches on the type of the first
argument::
>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615
Where there is no registered implementation for a specific type, its
method resolution order is used to find a more generic implementation.
The original function decorated with ``@singledispatch`` is registered
for the base ``object`` type, which means it is used if no better
implementation is found.
To check which implementation will the generic function choose for
a given type, use the ``dispatch()`` attribute::
>>> fun.dispatch(float)
>>> fun.dispatch(dict) # note: default implementation
To access all registered implementations, use the read-only ``registry``
attribute::
>>> fun.registry.keys()
dict_keys([, , ,
, ,
])
>>> fun.registry[float]
>>> fun.registry[object]
The vanilla documentation is available at
http://docs.python.org/3/library/functools.html#functools.singledispatch.
Versioning
----------
This backport is intended to keep 100% compatibility with the vanilla
release in Python 3.4+. To help maintaining a version you want and
expect, a versioning scheme is used where:
* the first three numbers indicate the version of Python 3.x from which the
backport is done
* a backport release number is provided after the last dot
For example, ``3.4.0.0`` is the **first** release of ``singledispatch``
compatible with the library found in Python **3.4.0**.
A single exception from the 100% compatibility principle is that bugs
fixed before releasing another minor Python 3.x.y version **will be
included** in the backport releases done in the mean time. This rule
applies to bugs only.
Maintenance
-----------
This backport is maintained on BitBucket by Łukasz Langa, one of the
members of the core CPython team:
* `singledispatch Mercurial repository `_
* `singledispatch issue tracker `_
Change Log
----------
3.4.0.2
~~~~~~~
Updated to the reference implementation as of 02-July-2013.
* more predictable dispatch order when abstract base classes are in use:
abstract base classes are now inserted into the MRO of the argument's
class where their functionality is introduced, i.e. issubclass(cls,
abc) returns True for the class itself but returns False for all its
direct base classes. Implicit ABCs for a given class (either
registered or inferred from the presence of a special method like
__len__) are inserted directly after the last ABC explicitly listed in
the MRO of said class. This also means there are less "ambiguous
dispatch" exceptions raised.
* better test coverage and improved docstrings
3.4.0.1
~~~~~~~
Updated to the reference implementation as of 31-May-2013.
* better performance
* fixed a corner case with PEP 435 enums
* calls to `dispatch()` also cached
* dispatching algorithm now now a module-level routine called `_find_impl()`
with a simplified implementation and proper documentation
* `dispatch()` now handles all caching-related activities
* terminology more consistent: "overload" -> "implementation"
3.4.0.0
~~~~~~~
* the first public release compatible with 3.4.0
Conversion Process
------------------
This section is technical and should bother you only if you are
wondering how this backport is produced. If the implementation details
of this backport are not important for you, feel free to ignore the
following content.
``singledispatch`` is converted using `six
`_ so that a single codebase can be
used for all compatible Python versions. Because a fully automatic
conversion was not doable, I took the following branching approach:
* the ``upstream`` branch holds unchanged files synchronized from the
upstream CPython repository. The synchronization is currently done by
manually copying the required code parts and stating from which
CPython changeset they come from. The tests should pass on Python 3.4
on this branch.
* the ``default`` branch holds the manually translated version and this
is where all tests are run for all supported Python versions using
Tox.
Keywords: single dispatch generic functions singledispatch genericfunctions decorator backport
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
singledispatch-3.4.0.2/singledispatch.egg-info/requires.txt 0000644 0000767 0000024 00000000003 12164513654 024024 0 ustar ambv staff 0000000 0000000 six singledispatch-3.4.0.2/singledispatch.egg-info/SOURCES.txt 0000644 0000767 0000024 00000000451 12164513654 023317 0 ustar ambv staff 0000000 0000000 MANIFEST.in
README.rst
setup.py
singledispatch.py
singledispatch_helpers.py
singledispatch.egg-info/PKG-INFO
singledispatch.egg-info/SOURCES.txt
singledispatch.egg-info/dependency_links.txt
singledispatch.egg-info/requires.txt
singledispatch.egg-info/top_level.txt
singledispatch.egg-info/zip-safe singledispatch-3.4.0.2/singledispatch.egg-info/top_level.txt 0000644 0000767 0000024 00000000046 12164513654 024165 0 ustar ambv staff 0000000 0000000 singledispatch
singledispatch_helpers
singledispatch-3.4.0.2/singledispatch.egg-info/zip-safe 0000644 0000767 0000024 00000000001 12150226135 023051 0 ustar ambv staff 0000000 0000000
singledispatch-3.4.0.2/singledispatch.py 0000644 0000767 0000024 00000020144 12164512672 020313 0 ustar ambv staff 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
__all__ = ['singledispatch']
from functools import update_wrapper
from weakref import WeakKeyDictionary
from singledispatch_helpers import MappingProxyType, get_cache_token
################################################################################
### singledispatch() - single-dispatch generic function decorator
################################################################################
def _c3_merge(sequences):
"""Merges MROs in *sequences* to a single MRO using the C3 algorithm.
Adapted from http://www.python.org/download/releases/2.3/mro/.
"""
result = []
while True:
sequences = [s for s in sequences if s] # purge empty sequences
if not sequences:
return result
for s1 in sequences: # find merge candidates among seq heads
candidate = s1[0]
for s2 in sequences:
if candidate in s2[1:]:
candidate = None
break # reject the current head, it appears later
else:
break
if not candidate:
raise RuntimeError("Inconsistent hierarchy")
result.append(candidate)
# remove the chosen candidate
for seq in sequences:
if seq[0] == candidate:
del seq[0]
def _c3_mro(cls, abcs=None):
"""Computes the method resolution order using extended C3 linearization.
If no *abcs* are given, the algorithm works exactly like the built-in C3
linearization used for method resolution.
If given, *abcs* is a list of abstract base classes that should be inserted
into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
result. The algorithm inserts ABCs where their functionality is introduced,
i.e. issubclass(cls, abc) returns True for the class itself but returns
False for all its direct base classes. Implicit ABCs for a given class
(either registered or inferred from the presence of a special method like
__len__) are inserted directly after the last ABC explicitly listed in the
MRO of said class. If two implicit ABCs end up next to each other in the
resulting MRO, their ordering depends on the order of types in *abcs*.
"""
for i, base in enumerate(reversed(cls.__bases__)):
if hasattr(base, '__abstractmethods__'):
boundary = len(cls.__bases__) - i
break # Bases up to the last explicit ABC are considered first.
else:
boundary = 0
abcs = list(abcs) if abcs else []
explicit_bases = list(cls.__bases__[:boundary])
abstract_bases = []
other_bases = list(cls.__bases__[boundary:])
for base in abcs:
if issubclass(cls, base) and not any(
issubclass(b, base) for b in cls.__bases__
):
# If *cls* is the class that introduces behaviour described by
# an ABC *base*, insert said ABC to its MRO.
abstract_bases.append(base)
for base in abstract_bases:
abcs.remove(base)
explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
return _c3_merge(
[[cls]] +
explicit_c3_mros + abstract_c3_mros + other_c3_mros +
[explicit_bases] + [abstract_bases] + [other_bases]
)
def _compose_mro(cls, types):
"""Calculates the method resolution order for a given class *cls*.
Includes relevant abstract base classes (with their respective bases) from
the *types* iterable. Uses a modified C3 linearization algorithm.
"""
bases = set(cls.__mro__)
# Remove entries which are already present in the __mro__ or unrelated.
def is_related(typ):
return (typ not in bases and hasattr(typ, '__mro__')
and issubclass(cls, typ))
types = [n for n in types if is_related(n)]
# Remove entries which are strict bases of other entries (they will end up
# in the MRO anyway.
def is_strict_base(typ):
for other in types:
if typ != other and typ in other.__mro__:
return True
return False
types = [n for n in types if not is_strict_base(n)]
# Subclasses of the ABCs in *types* which are also implemented by
# *cls* can be used to stabilize ABC ordering.
type_set = set(types)
mro = []
for typ in types:
found = []
for sub in typ.__subclasses__():
if sub not in bases and issubclass(cls, sub):
found.append([s for s in sub.__mro__ if s in type_set])
if not found:
mro.append(typ)
continue
# Favor subclasses with the biggest number of useful bases
found.sort(key=len, reverse=True)
for sub in found:
for subcls in sub:
if subcls not in mro:
mro.append(subcls)
return _c3_mro(cls, abcs=mro)
def _find_impl(cls, registry):
"""Returns the best matching implementation from *registry* for type *cls*.
Where there is no registered implementation for a specific type, its method
resolution order is used to find a more generic implementation.
Note: if *registry* does not contain an implementation for the base
*object* type, this function may return None.
"""
mro = _compose_mro(cls, registry.keys())
match = None
for t in mro:
if match is not None:
# If *match* is an implicit ABC but there is another unrelated,
# equally matching implicit ABC, refuse the temptation to guess.
if (t in registry and t not in cls.__mro__
and match not in cls.__mro__
and not issubclass(match, t)):
raise RuntimeError("Ambiguous dispatch: {0} or {1}".format(
match, t))
break
if t in registry:
match = t
return registry.get(match)
def singledispatch(func):
"""Single-dispatch generic function decorator.
Transforms a function into a generic function, which can have different
behaviours depending upon the type of its first argument. The decorated
function acts as the default implementation, and additional
implementations can be registered using the register() attribute of the
generic function.
"""
registry = {}
dispatch_cache = WeakKeyDictionary()
def ns(): pass
ns.cache_token = None
def dispatch(cls):
"""generic_func.dispatch(cls) ->
Runs the dispatch algorithm to return the best available implementation
for the given *cls* registered on *generic_func*.
"""
if ns.cache_token is not None:
current_token = get_cache_token()
if ns.cache_token != current_token:
dispatch_cache.clear()
ns.cache_token = current_token
try:
impl = dispatch_cache[cls]
except KeyError:
try:
impl = registry[cls]
except KeyError:
impl = _find_impl(cls, registry)
dispatch_cache[cls] = impl
return impl
def register(cls, func=None):
"""generic_func.register(cls, func) -> func
Registers a new implementation for the given *cls* on a *generic_func*.
"""
if func is None:
return lambda f: register(cls, f)
registry[cls] = func
if ns.cache_token is None and hasattr(cls, '__abstractmethods__'):
ns.cache_token = get_cache_token()
dispatch_cache.clear()
return func
def wrapper(*args, **kw):
return dispatch(args[0].__class__)(*args, **kw)
registry[object] = func
wrapper.register = register
wrapper.dispatch = dispatch
wrapper.registry = MappingProxyType(registry)
wrapper._clear_cache = dispatch_cache.clear
update_wrapper(wrapper, func)
return wrapper
singledispatch-3.4.0.2/singledispatch_helpers.py 0000644 0000767 0000024 00000012154 12164510173 022031 0 ustar ambv staff 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from abc import ABCMeta
from collections import MutableMapping
import sys
try:
from collections import UserDict
except ImportError:
from UserDict import UserDict
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
try:
from thread import get_ident
except ImportError:
try:
from _thread import get_ident
except ImportError:
from _dummy_thread import get_ident
def recursive_repr(fillvalue='...'):
'Decorator to make a repr function return fillvalue for a recursive call'
def decorating_function(user_function):
repr_running = set()
def wrapper(self):
key = id(self), get_ident()
if key in repr_running:
return fillvalue
repr_running.add(key)
try:
result = user_function(self)
finally:
repr_running.discard(key)
return result
# Can't use functools.wraps() here because of bootstrap issues
wrapper.__module__ = getattr(user_function, '__module__')
wrapper.__doc__ = getattr(user_function, '__doc__')
wrapper.__name__ = getattr(user_function, '__name__')
wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
return wrapper
return decorating_function
class ChainMap(MutableMapping):
''' A ChainMap groups multiple dicts (or other mappings) together
to create a single, updateable view.
The underlying mappings are stored in a list. That list is public and can
accessed or updated using the *maps* attribute. There is no other state.
Lookups search the underlying mappings successively until a key is found.
In contrast, writes, updates, and deletions only operate on the first
mapping.
'''
def __init__(self, *maps):
'''Initialize a ChainMap by setting *maps* to the given mappings.
If no mappings are provided, a single empty dictionary is used.
'''
self.maps = list(maps) or [{}] # always at least one map
def __missing__(self, key):
raise KeyError(key)
def __getitem__(self, key):
for mapping in self.maps:
try:
return mapping[key] # can't use 'key in mapping' with defaultdict
except KeyError:
pass
return self.__missing__(key) # support subclasses that define __missing__
def get(self, key, default=None):
return self[key] if key in self else default
def __len__(self):
return len(set().union(*self.maps)) # reuses stored hash values if possible
def __iter__(self):
return iter(set().union(*self.maps))
def __contains__(self, key):
return any(key in m for m in self.maps)
@recursive_repr()
def __repr__(self):
return '{0.__class__.__name__}({1})'.format(
self, ', '.join(map(repr, self.maps)))
@classmethod
def fromkeys(cls, iterable, *args):
'Create a ChainMap with a single dict created from the iterable.'
return cls(dict.fromkeys(iterable, *args))
def copy(self):
'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
return self.__class__(self.maps[0].copy(), *self.maps[1:])
__copy__ = copy
def new_child(self): # like Django's Context.push()
'New ChainMap with a new dict followed by all previous maps.'
return self.__class__({}, *self.maps)
@property
def parents(self): # like Django's Context.pop()
'New ChainMap from maps[1:].'
return self.__class__(*self.maps[1:])
def __setitem__(self, key, value):
self.maps[0][key] = value
def __delitem__(self, key):
try:
del self.maps[0][key]
except KeyError:
raise KeyError('Key not found in the first mapping: {!r}'.format(key))
def popitem(self):
'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
try:
return self.maps[0].popitem()
except KeyError:
raise KeyError('No keys found in the first mapping.')
def pop(self, key, *args):
'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
try:
return self.maps[0].pop(key, *args)
except KeyError:
raise KeyError('Key not found in the first mapping: {!r}'.format(key))
def clear(self):
'Clear maps[0], leaving maps[1:] intact.'
self.maps[0].clear()
class MappingProxyType(UserDict):
def __init__(self, data):
UserDict.__init__(self)
self.data = data
def get_cache_token():
return ABCMeta._abc_invalidation_counter
class Support(object):
def dummy(self):
pass
def cpython_only(self, func):
if 'PyPy' in sys.version:
return self.dummy
return func