diff options
Diffstat (limited to 'python/gevent/_util.py')
-rw-r--r-- | python/gevent/_util.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/python/gevent/_util.py b/python/gevent/_util.py new file mode 100644 index 0000000..4178a84 --- /dev/null +++ b/python/gevent/_util.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +""" +internal gevent utilities, not for external use. +""" + +from __future__ import print_function, absolute_import, division + +from gevent._compat import iteritems + + +class _NONE(object): + """ + A special object you must never pass to any gevent API. + Used as a marker object for keyword arguments that cannot have the + builtin None (because that might be a valid value). + """ + __slots__ = () + + def __repr__(self): + return '<default value>' + +_NONE = _NONE() + +def copy_globals(source, + globs, + only_names=None, + ignore_missing_names=False, + names_to_ignore=(), + dunder_names_to_keep=('__implements__', '__all__', '__imports__'), + cleanup_globs=True): + """ + Copy attributes defined in `source.__dict__` to the dictionary in globs + (which should be the caller's globals()). + + Names that start with `__` are ignored (unless they are in + *dunder_names_to_keep*). Anything found in *names_to_ignore* is + also ignored. + + If *only_names* is given, only those attributes will be considered. + In this case, *ignore_missing_names* says whether or not to raise an AttributeError + if one of those names can't be found. + + If cleanup_globs has a true value, then common things imported but not used + at runtime are removed, including this function. + + Returns a list of the names copied + """ + if only_names: + if ignore_missing_names: + items = ((k, getattr(source, k, _NONE)) for k in only_names) + else: + items = ((k, getattr(source, k)) for k in only_names) + else: + items = iteritems(source.__dict__) + + copied = [] + for key, value in items: + if value is _NONE: + continue + if key in names_to_ignore: + continue + if key.startswith("__") and key not in dunder_names_to_keep: + continue + globs[key] = value + copied.append(key) + + if cleanup_globs: + if 'copy_globals' in globs: + del globs['copy_globals'] + + return copied + +class Lazy(object): + """ + A non-data descriptor used just like @property. The + difference is the function value is assigned to the instance + dict the first time it is accessed and then the function is never + called agoin. + """ + def __init__(self, func): + self.data = (func, func.__name__) + + def __get__(self, inst, class_): + if inst is None: + return self + + func, name = self.data + value = func(inst) + inst.__dict__[name] = value + return value + +class readproperty(object): + """ + A non-data descriptor like @property. The difference is that + when the property is assigned to, it is cached in the instance + and the function is not called on that instance again. + """ + + def __init__(self, func): + self.func = func + + def __get__(self, inst, class_): + if inst is None: + return self + + return self.func(inst) |