You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.9 KiB

# -*- coding: utf-8 -*-
"""
internal gevent utilities, not for external use.
"""
from __future__ import print_function, absolute_import, division
from functools import update_wrapper
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 :func:`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 :exc:`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; this should be assigned to ``__imports__``.
"""
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
def import_c_accel(globs, cname):
"""
Import the C-accelerator for the __name__
and copy its globals.
"""
name = globs.get('__name__')
if not name or name == cname:
# Do nothing if we're being exec'd as a file (no name)
# or we're running from the C extension
return
from gevent._compat import PURE_PYTHON
if PURE_PYTHON:
return
import importlib
import warnings
with warnings.catch_warnings():
# Python 3.7 likes to produce
# "ImportWarning: can't resolve
# package from __spec__ or __package__, falling back on
# __name__ and __path__"
# when we load cython compiled files. This is probably a bug in
# Cython, but it doesn't seem to have any consequences, it's
# just annoying to see and can mess up our unittests.
warnings.simplefilter('ignore', ImportWarning)
mod = importlib.import_module(cname)
# By adopting the entire __dict__, we get a more accurate
# __file__ and module repr, plus we don't leak any imported
# things we no longer need.
globs.clear()
globs.update(mod.__dict__)
if 'import_c_accel' in globs:
del globs['import_c_accel']
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__)
update_wrapper(self, func)
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
update_wrapper(self, func)
def __get__(self, inst, class_):
if inst is None:
return self
return self.func(inst)
def gmctime():
"""
Returns the current time as a string in RFC3339 format.
"""
import time
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
try:
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import Attribute
except ImportError:
class Interface(object):
pass
def implementer(_iface):
def dec(c):
return c
return dec
def Attribute(s):
return s
Interface = Interface
implementer = implementer
Attribute = Attribute