|
|
- # originally inspired by "six" by Benjamin Peterson
-
- import inspect
- import sys
-
-
- if sys.version_info < (3,0):
- text_type = unicode
- binary_type = str
-
- import StringIO
- StringIO = BytesIO = StringIO.StringIO
- else:
- text_type = str
- binary_type = bytes
-
- import io
- StringIO = io.StringIO
- BytesIO = io.BytesIO
-
-
- def getargspec_permissive(func):
- """
- An `inspect.getargspec` with a relaxed sanity check to support Cython.
-
- Motivation:
-
- A Cython-compiled function is *not* an instance of Python's
- types.FunctionType. That is the sanity check the standard Py2
- library uses in `inspect.getargspec()`. So, an exception is raised
- when calling `argh.dispatch_command(cythonCompiledFunc)`. However,
- the CyFunctions do have perfectly usable `.func_code` and
- `.func_defaults` which is all `inspect.getargspec` needs.
-
- This function just copies `inspect.getargspec()` from the standard
- library but relaxes the test to a more duck-typing one of having
- both `.func_code` and `.func_defaults` attributes.
- """
- if inspect.ismethod(func):
- func = func.im_func
-
- # Py2 Stdlib uses isfunction(func) which is too strict for Cython-compiled
- # functions though such have perfectly usable func_code, func_defaults.
- if not (hasattr(func, "func_code") and hasattr(func, "func_defaults")):
- raise TypeError('{!r} missing func_code or func_defaults'.format(func))
-
- args, varargs, varkw = inspect.getargs(func.func_code)
- return inspect.ArgSpec(args, varargs, varkw, func.func_defaults)
-
-
- if sys.version_info < (3,0):
- getargspec = getargspec_permissive
- else:
- # in Python 3 the basic getargspec doesn't support keyword-only arguments
- # and annotations and raises ValueError if they are discovered
- getargspec = inspect.getfullargspec
-
-
- class _PrimitiveOrderedDict(dict):
- """
- A poor man's OrderedDict replacement for compatibility with Python 2.6.
- Implements only the basic features. May easily break if non-overloaded
- methods are used.
- """
- def __init__(self, *args, **kwargs):
- super(_PrimitiveOrderedDict, self).__init__(*args, **kwargs)
- self._seq = []
-
- def __setitem__(self, key, value):
- super(_PrimitiveOrderedDict, self).__setitem__(key, value)
- if key not in self._seq:
- self._seq.append(key)
-
- def __delitem__(self, key):
- super(_PrimitiveOrderedDict, self).__delitem__(key)
- idx = self._seq.index(key)
- del self._seq[idx]
-
- def __iter__(self):
- return iter(self._seq)
-
- def keys(self):
- return list(self)
-
- def values(self):
- return [self[k] for k in self]
-
-
- try:
- from collections import OrderedDict
- except ImportError:
- OrderedDict = _PrimitiveOrderedDict
|