diff options
author | shadchin <shadchin@yandex-team.com> | 2023-09-29 19:40:47 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.com> | 2023-09-29 21:02:37 +0300 |
commit | 009bb0299462be356e3d18de2642bfa8ec209511 (patch) | |
tree | 936d8ddcf496ffc4de33fbede5df33db3237b3fd /contrib/python/simplegeneric/py3/.dist-info | |
parent | 317a3cd8d45132dc3a55a9dcb2fb971ae7880158 (diff) | |
download | ydb-009bb0299462be356e3d18de2642bfa8ec209511.tar.gz |
Split simplegeneric on py2/py3
Diffstat (limited to 'contrib/python/simplegeneric/py3/.dist-info')
-rw-r--r-- | contrib/python/simplegeneric/py3/.dist-info/METADATA | 281 | ||||
-rw-r--r-- | contrib/python/simplegeneric/py3/.dist-info/top_level.txt | 1 |
2 files changed, 282 insertions, 0 deletions
diff --git a/contrib/python/simplegeneric/py3/.dist-info/METADATA b/contrib/python/simplegeneric/py3/.dist-info/METADATA new file mode 100644 index 0000000000..3b4df3f7d7 --- /dev/null +++ b/contrib/python/simplegeneric/py3/.dist-info/METADATA @@ -0,0 +1,281 @@ +Metadata-Version: 2.1 +Name: simplegeneric +Version: 0.8.1 +Summary: Simple generic functions (similar to Python's own len(), pickle.dump(), etc.) +Home-page: http://cheeseshop.python.org/pypi/simplegeneric +Author: Phillip J. Eby +Author-email: peak@eby-sarna.com +License: ZPL 2.1 +Platform: UNKNOWN +Classifier: Development Status :: 6 - Mature +Classifier: Development Status :: 7 - Inactive +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Zope Public License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.4 +Classifier: Programming Language :: Python :: 2.5 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: OS Independent +Classifier: Topic :: Software Development :: Libraries :: Python Modules + +* New in 0.8: Source and tests are compatible with Python 3 (w/o ``setup.py``) +* 0.8.1: setup.py is now compatible with Python 3 as well +* New in 0.7: `Multiple Types or Objects`_ +* New in 0.6: `Inspection and Extension`_, and thread-safe method registration + +The ``simplegeneric`` module lets you define simple single-dispatch +generic functions, akin to Python's built-in generic functions like +``len()``, ``iter()`` and so on. However, instead of using +specially-named methods, these generic functions use simple lookup +tables, akin to those used by e.g. ``pickle.dump()`` and other +generic functions found in the Python standard library. + +As you can see from the above examples, generic functions are actually +quite common in Python already, but there is no standard way to create +simple ones. This library attempts to fill that gap, as generic +functions are an `excellent alternative to the Visitor pattern`_, as +well as being a great substitute for most common uses of adaptation. + +This library tries to be the simplest possible implementation of generic +functions, and it therefore eschews the use of multiple or predicate +dispatch, as well as avoiding speedup techniques such as C dispatching +or code generation. But it has absolutely no dependencies, other than +Python 2.4, and the implementation is just a single Python module of +less than 100 lines. + + +Usage +----- + +Defining and using a generic function is straightforward:: + +>>> from simplegeneric import generic +>>> @generic +... def move(item, target): +... """Default implementation goes here""" +... print("what you say?!") + +>>> @move.when_type(int) +... def move_int(item, target): +... print("In AD %d, %s was beginning." % (item, target)) + +>>> @move.when_type(str) +... def move_str(item, target): +... print("How are you %s!!" % item) +... print("All your %s are belong to us." % (target,)) + +>>> zig = object() +>>> @move.when_object(zig) +... def move_zig(item, target): +... print("You know what you %s." % (target,)) +... print("For great justice!") + +>>> move(2101, "war") +In AD 2101, war was beginning. + +>>> move("gentlemen", "base") +How are you gentlemen!! +All your base are belong to us. + +>>> move(zig, "doing") +You know what you doing. +For great justice! + +>>> move(27.0, 56.2) +what you say?! + + +Inheritance and Allowed Types +----------------------------- + +Defining multiple methods for the same type or object is an error:: + +>>> @move.when_type(str) +... def this_is_wrong(item, target): +... pass +Traceback (most recent call last): +... +TypeError: <function move...> already has method for type <...'str'> + +>>> @move.when_object(zig) +... def this_is_wrong(item, target): pass +Traceback (most recent call last): +... +TypeError: <function move...> already has method for object <object ...> + +And the ``when_type()`` decorator only accepts classes or types:: + +>>> @move.when_type(23) +... def move_23(item, target): +... print("You have no chance to survive!") +Traceback (most recent call last): +... +TypeError: 23 is not a type or class + +Methods defined for supertypes are inherited following MRO order:: + +>>> class MyString(str): +... """String subclass""" + +>>> move(MyString("ladies"), "drinks") +How are you ladies!! +All your drinks are belong to us. + +Classic class instances are also supported (although the lookup process +is slower than for new-style instances):: + +>>> class X: pass +>>> class Y(X): pass + +>>> @move.when_type(X) +... def move_x(item, target): +... print("Someone set us up the %s!!!" % (target,)) + +>>> move(X(), "bomb") +Someone set us up the bomb!!! + +>>> move(Y(), "dance") +Someone set us up the dance!!! + + +Multiple Types or Objects +------------------------- + +As a convenience, you can now pass more than one type or object to the +registration methods:: + +>>> @generic +... def isbuiltin(ob): +... return False +>>> @isbuiltin.when_type(int, str, float, complex, type) +... @isbuiltin.when_object(None, Ellipsis) +... def yes(ob): +... return True + +>>> isbuiltin(1) +True +>>> isbuiltin(object) +True +>>> isbuiltin(object()) +False +>>> isbuiltin(X()) +False +>>> isbuiltin(None) +True +>>> isbuiltin(Ellipsis) +True + + +Defaults and Docs +----------------- + +You can obtain a function's default implementation using its ``default`` +attribute:: + +>>> @move.when_type(Y) +... def move_y(item, target): +... print("Someone set us up the %s!!!" % (target,)) +... move.default(item, target) + +>>> move(Y(), "dance") +Someone set us up the dance!!! +what you say?! + + +``help()`` and other documentation tools see generic functions as normal +function objects, with the same name, attributes, docstring, and module as +the prototype/default function:: + +>>> help(move) +Help on function move: +... +move(*args, **kw) +Default implementation goes here +... + + +Inspection and Extension +------------------------ + +You can find out if a generic function has a method for a type or object using +the ``has_object()`` and ``has_type()`` methods:: + +>>> move.has_object(zig) +True +>>> move.has_object(42) +False + +>>> move.has_type(X) +True +>>> move.has_type(float) +False + +Note that ``has_type()`` only queries whether there is a method registered for +the *exact* type, not subtypes or supertypes:: + +>>> class Z(X): pass +>>> move.has_type(Z) +False + +You can create a generic function that "inherits" from an existing generic +function by calling ``generic()`` on the existing function:: + +>>> move2 = generic(move) +>>> move(2101, "war") +In AD 2101, war was beginning. + +Any methods added to the new generic function override *all* methods in the +"base" function:: + +>>> @move2.when_type(X) +... def move2_X(item, target): +... print("You have no chance to survive make your %s!" % (target,)) + +>>> move2(X(), "time") +You have no chance to survive make your time! + +>>> move2(Y(), "time") +You have no chance to survive make your time! + +Notice that even though ``move()`` has a method for type ``Y``, the method +defined for ``X`` in ``move2()`` takes precedence. This is because the +``move`` function is used as the ``default`` method of ``move2``, and ``move2`` +has no method for type ``Y``:: + +>>> move2.default is move +True +>>> move.has_type(Y) +True +>>> move2.has_type(Y) +False + + +Limitations +----------- + +* The first argument is always used for dispatching, and it must always be +passed *positionally* when the function is called. + +* Documentation tools don't see the function's original argument signature, so +you have to describe it in the docstring. + +* If you have optional arguments, you must duplicate them on every method in +order for them to work correctly. (On the plus side, it means you can have +different defaults or required arguments for each method, although relying on +that quirk probably isn't a good idea.) + +These restrictions may be lifted in later releases, if I feel the need. They +would require runtime code generation the way I do it in ``RuleDispatch``, +however, which is somewhat of a pain. (Alternately I could use the +``BytecodeAssembler`` package to do the code generation, as that's a lot easier +to use than string-based code generation, but that would introduce more +dependencies, and I'm trying to keep this simple so I can just +toss it into Chandler without a big footprint increase.) + +.. _excellent alternative to the Visitor pattern: http://peak.telecommunity.com/DevCenter/VisitorRevisited + + + diff --git a/contrib/python/simplegeneric/py3/.dist-info/top_level.txt b/contrib/python/simplegeneric/py3/.dist-info/top_level.txt new file mode 100644 index 0000000000..ec4d598005 --- /dev/null +++ b/contrib/python/simplegeneric/py3/.dist-info/top_level.txt @@ -0,0 +1 @@ +simplegeneric |