Package: reg
Reg: Clever DispatchReg is a Python library that provides generic function support to
Python. It help you build powerful registration and configuration APIs
for your application, library or framework.Documentation.Build StatusCHANGES0.12 (2020-01-29)Breaking changereg.arginfo(callable) returns now a FullArgSpec tuple
instead of the deprecated ArgSpec tuple. FullArgSpec has
full support for annotations and keyword-only parameters.Fixes#55.Removed: Removed support for Python 2.You have to upgrade to Python 3 if you want to use this version.Dropped support for Python 3.3.Added support for Python 3.5, 3.6, 3.7, 3.8 and PyPy 3.6.Make Python 3.7 the default testing environment.Add integration for the Black code formatter.0.11 (2016-12-23)Breaking changeThekey_predicatefunction is gone.  You can now usePredicate(...,index=KeyIndex)ormatch_keyinstead.Breaking changeTheclass_predicatefunction is gone.  You can now usePredicate(...,index=ClassIndex),match_instanceormatch_classinstead.Breaking changeThe undocumentedSentinelclass andNOT_FOUNDobject are
gone.Breaking changeThe classPredicateRegistryis not longer part of the API.
Internally, the classesMultiPredicate,MultiIndex,SingleValueRegistryhave all been merged intoPredicateRegistry, which should now considered an implementation
detail.The second argument formatch_keyis now optional; if you
don’t supply itmatch_keywill generate a predicate function
that extracts that name by default.The documentation now includes a section describing the internals of
Reg.Upload universal wheels to pypi during release.0.10 (2016-10-04)Breaking changeReg has undergone another API breaking change. The goals of this
change were:Make everything explicit.A simpler implementation structure – dispatch functions maintain
their own registries, which allows for less interacting objects.Make the advanced context-dependent dispatch more Pythonic by
using classes with special dispatch methods.Detailed changes:reg.Registryis gone. Instead you register directly on the
dispatch function:@reg.dispatch('a')
def foo(a):
  ...

def foo_implementation(a):
  ...

foo.register(foo_implementation, a=Document)Caching is now per dispatch function, not globally per lookup. You
can pass aget_key_lookupfunction that wrapsreg.PredicateRegistryinstance inside areg.DictCachingKeyLookupcache. You can also use areg.LruCachingKeyLookupif you expect a dispatch to be called
with a large amount of possible predicate combinations, to
preserve memory.The whole concept of a “lookup” is gone:reg.implicitis gone: everything is explicit. There is no more
implicit lookup.reg.Lookupitself is gone – its now implemented directly in the
dispatch object, but was already how you accessed it.The speciallookupargument to pass through the currentLookupis gone. If you need context-dependent dispatch, you
use dispatch methods.If you need context dependent dispatch, where the functions
being dispatched to depend on application context (such as
Morepath’s application mounting), you usereg.dispatch_methodto create a dispatch method. A dispatch
method maintains an entirely separate dispatch registry for each
subclass. You usereg.methodifyto register a dispatch
function that takes an optional context first argument.If you do not use the context-dependent dispatch feature, then to
upgrade your code:remove anyreg.set_implicitfrom your code, setup ofLookupand the like.If you use an explicitlookupargument you can just remove them.You also need to change your registration code: no morereg.Registrysetup.Change your registrations to be on the dispatch objects itself
usingDispatch.register.To enable caching you need to set upget_key_lookupon the
dispatch functions. You can create a partially applied version ofdispatchto make this less verbose:import reg
from functools import partial

def get_caching_key_lookup(r):
    return reg.CachingKeyLookup(r, 5000, 5000, 5000)

dispatch = partial(reg.dispatch, get_key_lookup=get_caching_key_lookup)dispatch_external_predicatesis gone. Just usedispatchdirectly.  You can add predicates to an existing Dispatch object
using theadd_predicatesmethod.If you do use the context-dependent dispatch feature, then you also
need to:identify the context class in your application (or create one).move the dispatch functions to this class, marking them with@reg.dispatch_methodinstead of@reg.dispatch.Registration is now using<context_class>.<method>.register. Functions you register this
way behave as methods tocontext_class, so get an instance of
this class as the first argument.You can also usereg.methodifyto register implementation
functions that do not take the context as the first argument –
this is useful when upgrading existing code.Call your context-dependent methods as methods on the context
instance. This way you can indicate what context you are calling
your dispatch methods in, instead of using thelookup`argument.In some cases you want a context-dependent method that actually does
not dispatch on any of its arguments. To support this use case you
can simply set function (that takes an app argument) as a the method
on the context class directly:Context.my_method = some_functionIf you want to set up a function that doesn’t take a reference to aContextinstance as its first argument, you can usereg.methodifyto turn it into a method that ignores its first
argument:Context.my_method = reg.methodify(some_function)If you want to register a function that might or might not have a
reference to aContextinstance as its first argument, called,
e.g.,app, you can use the following:Context.my_method = reg.methodify(some_function, selfname='app')Breaking changeRemoved the helper functionmapplyfrom the API.Breaking changeRemoved the exception classKeyExtractorErrorfrom the API.
When passing the wrong number of arguments to a dispatch function,
or when using the wrong argument names, you will now get a
TypeError, in conformity with standard Python behaviour.Breaking changeRemoved theKeyExtractorclass from the API. Callables used in
predicate construction now expect the same arguments as the dispatch
function.Breaking changeRemoved theargnamesattribute fromPredicateand its
descendant.Breaking changeRemove thematch_argnamepredicate.  You can now usematch_instancewith no callable instead.The second argument formatch_classis now optional; if you
don’t supply itmatch_classwill generate a predicate function
that extracts that name by default.The second argument formatch_instanceis now optional; if you
don’t supply itmatch_instancewill generate a predicate function
that extracts that name by default.Include doctests in Tox and Travis.We now use virtualenv and pip instead of buildout to set up the
development environment. The development documentation has been
updated accordingly.As we reached 100% code coverage for pytest, coveralls integration
was replaced by the--fail-under=100argument ofcoverage reportin the tox coverage test.0.9.3 (2016-07-18)Minor fixes to documentation.Add tox test environments for Python 3.4 and 3.5, PyPy 3 and PEP 8.Make Python 3.5 the default Python environment.Changed locationNoImplicitLookupErrorwas imported from in__init__.py.0.9.2 (2014-11-13)Reg was a bit too strict; when you had multiple (but not single)
predicates, Reg would raise KeyError when you put in an unknown
key. Now they’re just being silently ignored, as they don’t do any
harm.Eliminated a check inArgExtractorthat could never take place.Bring test coverage back up to 100%.Add converage configuration to ignore test files in coverage
reporting.0.9.1 (2014-11-11)A bugfix in the behavior of the fallback logic. In situations with
multiple predicates of which one is a class predicate it was
possible for a fallback not to be found even though a fallback was
available.0.9 (2014-11-11)Total rewrite of Reg! This includes a range of changes that can break
code. The primary motivations for this rewrite:unify predicate system with class-based lookup system.extract dispatch information from specific arguments instead of all
arguments.Some specific changes:Replaced@reg.genericdecorator with@reg.dispatch()decorator. This decorator can be configured with predicates that
extract information from the arguments. Rewrite this:@reg.generic
def foo(obj):
   passto this:@reg.dispatch('obj')
def foo(obj):
   passAnd this:@reg.generic
def bar(a, b):
    passTo this:@reg.dispatch('a', 'b')
def bar(a, b):
    passThis is to get dispatch on the classes of these instance
arguments. If you want to match on the class of an attribute of
an argument (for instance) you can usematch_instancewith a function:@reg.dispatch(match_instance('a', lambda a: a.attr))The first argument tomatch_instanceis the name of the
predicate by which you refer to it inregister_function.You can also usematch_classto have direct dispatch on classes
(useful for replicating classmethods), andmatch_keyto have
dispatch on the (immutable) value of the argument (useful for a view
predicate system). Like formatch_instance, you supply functions
to these match functions that extract the exact information to
dispatch on from the argument.Theregister_functionAPI replaces theregisterAPI to
register a function. Replace this:r.register(foo, (SomeClass,), dispatched_to)with:r.register_function(foo, dispatched_to, obj=SomeClass)You now use keyword parameters to indicate exactly those arguments
specified byreg.dispatch()are actually predicate
arguments. You don’t need to worry about the order of predicates
anymore when you register a function for it.The newclassgenericfunctionality is part of the predicate
system now; you can usereg.match_classinstead. Replace:@reg.classgeneric
def foo(cls):
   passwith:@reg.dispatch(reg.match_class('cls', lambda cls: cls))
def foo(cls):
    passYou can do this with any argument now, not just the first one.pep443 support is gone. Reg is focused on its own dispatch system.Compose functionality is gone – it turns out Morepath doesn’t use
lookup composition to support App inheritance. The cached lookup
functionality has moved intoregistry.pyand now also supports
caching of predicate-based lookups.Dependency on the future module is gone in favor of a small amount
of compatibility code.0.8 (2014-08-28)Added a@reg.classgeneric. This is like@reg.generic, but
the first argument is treated as a class, not as an instance. This
makes it possible to replace@classmethodwith a generic
function too.Fix documentation on running documentation tests. For some reason
this did not work properly anymore without running sphinxpython
explicitly.Optimization: improve performance of generic function calls by
employinglookup_mapplyinstead of generalmapply, as we
only care about passing in the lookup argument when it’s defined,
and any other arguments should work as before. Also added aperf.pywhich is a simple generic function timing script.0.7 (2014-06-17)Python 2.6 compatibility. (Ivo van der Wijk)Class maps (and thus generic function lookup) now works with old
style classes as well.Marked as production/stable now insetup.py.0.6 (2014-04-08)Removed unused code from mapply.py.Typo fix in API docs.0.5 (2014-01-21)Makereg.ANYpublic. Used for predicates that match any value.0.4 (2014-01-14)arginfo has been totally rewritten and is now part of the public API of reg.0.3 (2014-01-06)Experimental Python 3.3 support thanks to the future module.0.2 (2013-12-19)If a generic function implementation defines alookupargument
that argument will be the lookup used to call it.Addedreg.mapply(). This allows you to call things with more
keyword arguments than it accepts, ignoring those extra keyword
args.A function that returnsNoneis not assumed to fail, so no fallback
to the original generic function is triggered anymore.An optionalprecalcfacility is made available onMatcherto
avoid some recalculation.Implement a specificPredicateMatcherthat matches a value on
predicate.0.1 (2013-10-28)Initial public release.