aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/_util.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/gevent/_util.py')
-rw-r--r--python/gevent/_util.py106
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)