Skip to content

Instantly share code, notes, and snippets.

@cdent
Created July 30, 2016 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdent/de50cb05a7ab8219cd4f5b4ab3c181dd to your computer and use it in GitHub Desktop.
Save cdent/de50cb05a7ab8219cd4f5b4ab3c181dd to your computer and use it in GitHub Desktop.
import inspect
import collections
LATEST = 5.0
METHODS = collections.defaultdict(list)
# From twisted
# https://github.com/twisted/twisted/blob/trunk/twisted/python/deprecate.py
def _fullyQualifiedName(obj):
"""
Return the fully qualified name of a module, class, method or function.
Classes and functions need to be module level ones to be correctly
qualified.
@rtype: C{str}.
"""
try:
name = obj.__qualname__
except AttributeError:
name = obj.__name__
if inspect.isclass(obj) or inspect.isfunction(obj):
moduleName = obj.__module__
return "%s.%s" % (moduleName, name)
elif inspect.ismethod(obj):
try:
cls = obj.im_class
except AttributeError:
# Python 3 eliminates im_class, substitutes __module__ and
# __qualname__ to provide similar information.
return "%s.%s" % (obj.__module__, obj.__qualname__)
else:
className = _fullyQualifiedName(cls)
return "%s.%s" % (className, name)
return name
def find_method(f, version_float):
"""Look in METHODS for method with right name matching version."""
method_list = METHODS[f.__name__]
for min_version, max_version, func in method_list:
if min_version <= version_float <= max_version:
return func
# no match found we need to go boom
raise ValueError('that version sucks %s' % version_float)
def mdec(min_version_string, max_version_string=None):
"""Build a dictionary of METHODS.
The key is the fully qualified name of the method.
The value is a list, highest to lowest, of the versioned methods
that do this thing.
"""
def decorator(f):
min_version_float = float(min_version_string)
if max_version_string:
max_version_float = float(max_version_string)
else:
max_version_float = LATEST
qualified_name = _fullyQualifiedName(f)
METHODS[f.__name__].append((min_version_float, max_version_float, f))
def decorated_func(req, *args, **kwargs):
version_float = float(req['version_string'])
return find_method(f, version_float)(req, *args, **kwargs)
# Sort highest min version to beginning of list.
METHODS[f.__name__].sort(key=lambda x: x[0], reverse=True)
return decorated_func
return decorator
@mdec('1.1')
def thing(req):
print 'in some'
@mdec('1.2')
def thing(req):
print 'in none'
@mdec('0.9')
def thing(req):
print 'in low'
@mdec('1.1')
def house(req):
print 'in dec house'
@mdec('1.2')
def house(req):
print 'in undec house'
if __name__ == '__main__':
req = {}
req['version_string'] = '1.1'
thing(req)
house(req)
req['version_string'] = '1.2'
thing(req)
house(req)
req['version_string'] = '1.9'
thing(req)
house(req)
req['version_string'] = '0.9'
try:
thing(req)
except ValueError as exc:
print 'thing', exc
try:
house(req)
except ValueError as exc:
print 'house', exc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment