Current File : //opt/eff.org/certbot/venv/lib64/python2.7/site-packages/zope/deferredimport/deferredmodule.py |
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Modules with defered attributes
"""
import sys
import warnings
import zope.proxy
class Deferred(object):
def __init__(self, name, specifier):
self.__name__ = name
self.specifier = specifier
_import_chicken = {}, {}, ['*']
def get(self):
specifier = self.specifier
if ':' in specifier:
module, name = specifier.split(':')
else:
module, name = specifier, ''
v = __import__(module, *self._import_chicken)
if name:
for n in name.split('.'):
v = getattr(v, n)
return v
class DeferredAndDeprecated(Deferred):
def __init__(self, name, specifier, message):
super(DeferredAndDeprecated, self).__init__(name, specifier)
self.message = message
def get(self):
warnings.warn(
self.__name__ + " is deprecated. " + self.message,
DeprecationWarning, stacklevel=3)
return super(DeferredAndDeprecated, self).get()
class ModuleProxy(zope.proxy.ProxyBase):
__slots__ = ('__deferred_definitions__', '__doc__')
def __init__(self, module):
super(ModuleProxy, self).__init__(module)
self.__deferred_definitions__ = {}
self.__doc__ = module.__doc__
def __getattr__(self, name):
try:
get = self.__deferred_definitions__[name]
except KeyError:
raise AttributeError(name)
v = get.get()
setattr(self, name, v)
try:
del self.__deferred_definitions__[name]
except KeyError: # pragma: no cover
pass
return v
def initialize(level=1):
"""Prepare a module to support deferred imports.
Modules do not need to call this directly, because the
`define*` and `deprecated*` functions call it.
This is intended to be called from the module to be prepared.
The implementation wraps a proxy around the module and replaces
the entry in sys.modules with the proxy. It does no harm to
call this function more than once for a given module, because
this function does not re-wrap a proxied module.
The level parameter specifies a relative stack depth.
When this function is called directly by the module, level should be 1.
When this function is called by a helper function, level should
increase with the depth of the stack.
Returns nothing when level is 1; otherwise returns the proxied module.
"""
__name__ = sys._getframe(level).f_globals['__name__']
module = sys.modules[__name__]
if type(module) is not ModuleProxy:
module = ModuleProxy(module)
sys.modules[__name__] = module
if level == 1:
return
return module
def define(**names):
"""Define deferred imports using keyword parameters.
Each parameter specifies the importable name and how to import it.
Use `module:name` syntax to import a name from a module, or `module`
(no colon) to import a module.
"""
module = initialize(2)
__deferred_definitions__ = module.__deferred_definitions__
for name, specifier in names.items():
__deferred_definitions__[name] = Deferred(name, specifier)
def defineFrom(from_name, *names):
"""Define deferred imports from a particular module.
The from_name specifies which module to import.
The rest of the parameters specify names to import from that module.
"""
module = initialize(2)
__deferred_definitions__ = module.__deferred_definitions__
for name in names:
specifier = from_name + ':' + name
__deferred_definitions__[name] = Deferred(name, specifier)
def deprecated(message, **names):
"""Define deferred and deprecated imports using keyword parameters.
The first use of each name will generate a deprecation warning with
the given message.
Each parameter specifies the importable name and how to import it.
Use `module:name` syntax to import a name from a module, or `module`
(no colon) to import a module.
"""
module = initialize(2)
__deferred_definitions__ = module.__deferred_definitions__
for name, specifier in names.items():
__deferred_definitions__[name] = DeferredAndDeprecated(
name, specifier, message)
def deprecatedFrom(message, from_name, *names):
"""Define deferred and deprecated imports from a particular module.
The first use of each name will generate a deprecation warning with
the given message.
The from_name specifies which module to import.
The rest of the parameters specify names to import from that module.
"""
module = initialize(2)
__deferred_definitions__ = module.__deferred_definitions__
for name in names:
specifier = from_name + ':' + name
__deferred_definitions__[name] = DeferredAndDeprecated(
name, specifier, message)