📄 util.py
字号:
# util.py# Copyright (C) 2005, 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com## This module is part of SQLAlchemy and is released under# the MIT License: http://www.opensource.org/licenses/mit-license.phpimport inspect, itertools, sets, sys, warnings, weakrefimport __builtin__types = __import__('types')from sqlalchemy import exceptionstry: import thread, threadingexcept ImportError: import dummy_thread as thread import dummy_threading as threadingtry: Set = set set_types = set, sets.Setexcept NameError: set_types = sets.Set, # layer some of __builtin__.set's binop behavior onto sets.Set class Set(sets.Set): def _binary_sanity_check(self, other): pass def issubset(self, iterable): other = type(self)(iterable) return sets.Set.issubset(self, other) def __le__(self, other): sets.Set._binary_sanity_check(self, other) return sets.Set.__le__(self, other) def issuperset(self, iterable): other = type(self)(iterable) return sets.Set.issuperset(self, other) def __ge__(self, other): sets.Set._binary_sanity_check(self, other) return sets.Set.__ge__(self, other) # lt and gt still require a BaseSet def __lt__(self, other): sets.Set._binary_sanity_check(self, other) return sets.Set.__lt__(self, other) def __gt__(self, other): sets.Set._binary_sanity_check(self, other) return sets.Set.__gt__(self, other) def __ior__(self, other): if not isinstance(other, sets.BaseSet): return NotImplemented return sets.Set.__ior__(self, other) def __iand__(self, other): if not isinstance(other, sets.BaseSet): return NotImplemented return sets.Set.__iand__(self, other) def __ixor__(self, other): if not isinstance(other, sets.BaseSet): return NotImplemented return sets.Set.__ixor__(self, other) def __isub__(self, other): if not isinstance(other, sets.BaseSet): return NotImplemented return sets.Set.__isub__(self, other)try: import cPickle as pickleexcept ImportError: import pickletry: reversed = __builtin__.reversedexcept AttributeError: def reversed(seq): i = len(seq) -1 while i >= 0: yield seq[i] i -= 1 raise StopIteration()try: # Try the standard decimal for > 2.3 or the compatibility module # for 2.3, if installed. from decimal import Decimal decimal_type = Decimalexcept ImportError: def Decimal(arg): if Decimal.warn: warn("True Decimal types not available on this Python, " "falling back to floats.") Decimal.warn = False return float(arg) Decimal.warn = True decimal_type = floattry: from operator import attrgetterexcept: def attrgetter(attribute): return lambda value: getattr(value, attribute)if sys.version_info >= (2, 5): class PopulateDict(dict): """a dict which populates missing values via a creation function. note the creation function takes a key, unlike collections.defaultdict. """ def __init__(self, creator): self.creator = creator def __missing__(self, key): self[key] = val = self.creator(key) return valelse: class PopulateDict(dict): """a dict which populates missing values via a creation function.""" def __init__(self, creator): self.creator = creator def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: self[key] = value = self.creator(key) return valuetry: from collections import defaultdictexcept ImportError: class defaultdict(dict): def __init__(self, default_factory=None, *a, **kw): if (default_factory is not None and not hasattr(default_factory, '__call__')): raise TypeError('first argument must be callable') dict.__init__(self, *a, **kw) self.default_factory = default_factory def __getitem__(self, key): try: return dict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() return value def __reduce__(self): if self.default_factory is None: args = tuple() else: args = self.default_factory, return type(self), args, None, None, self.iteritems() def copy(self): return self.__copy__() def __copy__(self): return type(self)(self.default_factory, self) def __deepcopy__(self, memo): import copy return type(self)(self.default_factory, copy.deepcopy(self.items())) def __repr__(self): return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))def to_list(x, default=None): if x is None: return default if not isinstance(x, (list, tuple)): return [x] else: return xdef to_set(x): if x is None: return Set() if not isinstance(x, Set): return Set(to_list(x)) else: return xdef to_ascii(x): """Convert Unicode or a string with unknown encoding into ASCII.""" if isinstance(x, str): return x.encode('string_escape') elif isinstance(x, unicode): return x.encode('unicode_escape') else: raise TypeErrordef flatten_iterator(x): """Given an iterator of which further sub-elements may also be iterators, flatten the sub-elements into a single iterator. """ for elem in x: if hasattr(elem, '__iter__'): for y in flatten_iterator(elem): yield y else: yield elemclass ArgSingleton(type): instances = weakref.WeakValueDictionary() def dispose(cls): for key in list(ArgSingleton.instances): if key[0] is cls: del ArgSingleton.instances[key] dispose = staticmethod(dispose) def __call__(self, *args): hashkey = (self, args) try: return ArgSingleton.instances[hashkey] except KeyError: instance = type.__call__(self, *args) ArgSingleton.instances[hashkey] = instance return instancedef get_cls_kwargs(cls): """Return the full set of inherited kwargs for the given `cls`. Probes a class's __init__ method, collecting all named arguments. If the __init__ defines a **kwargs catch-all, then the constructor is presumed to pass along unrecognized keywords to it's base classes, and the collection process is repeated recursively on each of the bases. """ for c in cls.__mro__: if '__init__' in c.__dict__: stack = Set([c]) break else: return [] args = Set() while stack: class_ = stack.pop() ctr = class_.__dict__.get('__init__', False) if not ctr or not isinstance(ctr, types.FunctionType): continue names, _, has_kw, _ = inspect.getargspec(ctr) args.update(names) if has_kw: stack.update(class_.__bases__) args.discard('self') return list(args)def get_func_kwargs(func): """Return the full set of legal kwargs for the given `func`.""" return inspect.getargspec(func)[0]# from paste.deploy.convertersdef asbool(obj): if isinstance(obj, (str, unicode)): obj = obj.strip().lower() if obj in ['true', 'yes', 'on', 'y', 't', '1']: return True elif obj in ['false', 'no', 'off', 'n', 'f', '0']: return False else: raise ValueError("String is not true/false: %r" % obj) return bool(obj)def coerce_kw_type(kw, key, type_, flexi_bool=True): """If 'key' is present in dict 'kw', coerce its value to type 'type_' if necessary. If 'flexi_bool' is True, the string '0' is considered false when coercing to boolean. """ if key in kw and type(kw[key]) is not type_ and kw[key] is not None: if type_ is bool and flexi_bool: kw[key] = asbool(kw[key]) else: kw[key] = type_(kw[key])def duck_type_collection(specimen, default=None): """Given an instance or class, guess if it is or is acting as one of the basic collection types: list, set and dict. If the __emulates__ property is present, return that preferentially. """ if hasattr(specimen, '__emulates__'): # canonicalize set vs sets.Set to a standard: util.Set if (specimen.__emulates__ is not None and issubclass(specimen.__emulates__, set_types)): return Set else: return specimen.__emulates__ isa = isinstance(specimen, type) and issubclass or isinstance if isa(specimen, list): return list if isa(specimen, set_types): return Set if isa(specimen, dict): return dict if hasattr(specimen, 'append'): return list elif hasattr(specimen, 'add'): return Set elif hasattr(specimen, 'set'): return dict else: return defaultdef dictlike_iteritems(dictlike): """Return a (key, value) iterator for almost any dict-like object.""" if hasattr(dictlike, 'iteritems'): return dictlike.iteritems() elif hasattr(dictlike, 'items'): return iter(dictlike.items()) getter = getattr(dictlike, '__getitem__', getattr(dictlike, 'get', None)) if getter is None: raise TypeError( "Object '%r' is not dict-like" % dictlike) if hasattr(dictlike, 'iterkeys'): def iterator(): for key in dictlike.iterkeys(): yield key, getter(key) return iterator() elif hasattr(dictlike, 'keys'): return iter([(key, getter(key)) for key in dictlike.keys()]) else: raise TypeError( "Object '%r' is not dict-like" % dictlike)def assert_arg_type(arg, argtype, name): if isinstance(arg, argtype): return arg else: if isinstance(argtype, tuple): raise exceptions.ArgumentError("Argument '%s' is expected to be one of type %s, got '%s'" % (name, ' or '.join(["'%s'" % str(a) for a in argtype]), str(type(arg)))) else: raise exceptions.ArgumentError("Argument '%s' is expected to be of type '%s', got '%s'" % (name, str(argtype), str(type(arg))))def warn_exception(func, *args, **kwargs): """executes the given function, catches all exceptions and converts to a warning.""" try: return func(*args, **kwargs) except: warn("%s('%s') ignored" % sys.exc_info()[0:2])class SimpleProperty(object): """A *default* property accessor.""" def __init__(self, key): self.key = key def __set__(self, obj, value): setattr(obj, self.key, value) def __delete__(self, obj): delattr(obj, self.key) def __get__(self, obj, owner): if obj is None: return self else: return getattr(obj, self.key)class NotImplProperty(object): """a property that raises ``NotImplementedError``.""" def __init__(self, doc): self.__doc__ = doc def __set__(self, obj, value): raise NotImplementedError() def __delete__(self, obj): raise NotImplementedError() def __get__(self, obj, owner): if obj is None: return self else: raise NotImplementedError()class OrderedProperties(object): """An object that maintains the order in which attributes are set upon it. Also provides an iterator and a very basic getitem/setitem interface to those attributes. (Not really a dict, since it iterates over values, not keys. Not really a list, either, since each value must have a key associated; hence there is no append or extend.) """ def __init__(self): self.__dict__['_data'] = OrderedDict() def __len__(self): return len(self._data) def __iter__(self): return self._data.itervalues() def __add__(self, other): return list(self) + list(other) def __setitem__(self, key, object): self._data[key] = object def __getitem__(self, key): return self._data[key] def __delitem__(self, key): del self._data[key] def __setattr__(self, key, object): self._data[key] = object def __getstate__(self): return {'_data': self.__dict__['_data']} def __setstate__(self, state): self.__dict__['_data'] = state['_data'] def __getattr__(self, key): try: return self._data[key] except KeyError: raise AttributeError(key) def __contains__(self, key): return key in self._data def get(self, key, default=None): if key in self: return self[key] else: return default def keys(self): return self._data.keys() def has_key(self, key): return self._data.has_key(key) def clear(self): self._data.clear()class OrderedDict(dict): """A Dictionary that returns keys/values/items in the order they were added.""" def __init__(self, ____sequence=None, **kwargs): self._list = [] if ____sequence is None: if kwargs: self.update(**kwargs) else: self.update(____sequence, **kwargs) def clear(self): self._list = [] dict.clear(self) def update(self, ____sequence=None, **kwargs): if ____sequence is not None: if hasattr(____sequence, 'keys'): for key in ____sequence.keys(): self.__setitem__(key, ____sequence[key]) else: for key, value in ____sequence: self[key] = value if kwargs: self.update(kwargs) def setdefault(self, key, value): if key not in self: self.__setitem__(key, value) return value else: return self.__getitem__(key) def __iter__(self): return iter(self._list) def values(self): return [self[key] for key in self._list] def itervalues(self): return iter(self.values()) def keys(self): return list(self._list) def iterkeys(self): return iter(self.keys()) def items(self): return [(key, self[key]) for key in self.keys()] def iteritems(self): return iter(self.items())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -