[Zope3-checkins]
SVN: Zope3/branches/jim-adapter/src/zope/deferredimport/
Defered import mechanism
Jim Fulton
jim at zope.com
Mon Feb 20 16:54:13 EST 2006
Log message for revision 41716:
Defered import mechanism
Changed:
A Zope3/branches/jim-adapter/src/zope/deferredimport/
A Zope3/branches/jim-adapter/src/zope/deferredimport/README.txt
A Zope3/branches/jim-adapter/src/zope/deferredimport/__init__.py
A Zope3/branches/jim-adapter/src/zope/deferredimport/deferredmodule.py
A Zope3/branches/jim-adapter/src/zope/deferredimport/sample1.py.in
A Zope3/branches/jim-adapter/src/zope/deferredimport/sample2.py.in
A Zope3/branches/jim-adapter/src/zope/deferredimport/tests.py
-=-
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/README.txt
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/README.txt 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/README.txt 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1,58 @@
+Deferred Import
+===============
+
+Often, especially for package modules, you want to import names for
+convenience, but not actually perform the imports until necessary.
+
+The zope.deferredimport.define function supports this. You can use
+the function to define one or more names to be imported when they are
+accessed. Simply provide names as keyword arguments with import
+specifiers as values. The import specifiers are given as atrings of
+the form "module:name", where module is the dotted name of the
+module and name is a, possibly dotted, name of an object within the
+module.
+
+To see how this works, see the sample modules, sample1 and sample2.
+The sample1 module defines several values as deferred imports of and
+from sample 2. The sample2 module prints a message when it is
+imported. When we import sample1, we don't see a message until we
+access a variable:
+
+ >>> import zope.deferredimport.sample1
+ >>> print zope.deferredimport.sample1.one
+ Sampe 2 imported!
+ 1
+
+ >>> import zope.deferredimport.sample2
+
+ >>> zope.deferredimport.sample1.sample2 is zope.deferredimport.sample2
+ True
+
+Note that a deferred attribute appears in a module's dictionary *after*
+it is accessed the first time:
+
+ >>> 'two' in zope.deferredimport.sample1.__dict__
+ False
+
+ >>> zope.deferredimport.sample1.two
+ 2
+
+ >>> 'two' in zope.deferredimport.sample1.__dict__
+ True
+
+Deferred attributes can also be marked as deprecated, in which case, a
+message will be printed the first time they are accessed:
+
+ >>> zope.deferredimport.sample1.three is zope.deferredimport.sample2.C
+ README.txt:1:
+ DeprecationWarning: three is deprecated. Will go away in 2007.
+ Deferred Import
+ True
+
+Of course, non-deferred variables are accessible as usuall:
+
+ >>> print zope.deferredimport.sample1.four
+ 4
+
+ >>> print zope.deferredimport.sample1.five
+ 5
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/__init__.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/__init__.py 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/__init__.py 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1 @@
+from zope.deferredimport.deferredmodule import define, deprecated
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/deferredmodule.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/deferredmodule.py 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/deferredmodule.py 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1,93 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation 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
+
+$Id$
+"""
+
+import sys
+import warnings
+
+class Module(object):
+
+ def __init__(self, old):
+ self.__dict__ = old.__dict__
+ self.__original_module__ = old
+
+ def __repr__(self):
+ return `self.__original_module__`
+
+class Deferred(object):
+
+ def __init__(self, name, specifier):
+ self.__name__ = name
+ self.specifier = specifier
+
+ _import_chicken = {}, {}, ['*']
+
+ def __get__(self, inst, class_):
+ if inst is None:
+ return 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)
+ setattr(inst, self.__name__, v)
+ return v
+
+class DeferredAndDeprecated(Deferred):
+
+ def __init__(self, name, specifier, message):
+ self.__name__ = name
+ self.specifier = specifier
+ self.message = message
+
+
+ def __get__(self, inst, class_):
+ if inst is None:
+ return self
+
+ warnings.warn(
+ self.__name__ + " is deprecated. " + self.message,
+ DeprecationWarning, stacklevel=2)
+ return Deferred.__get__(self, inst, class_)
+
+
+def getClass():
+ __name__ = sys._getframe(2).f_globals['__name__']
+ module = sys.modules[__name__]
+ cls = module.__class__
+ if not issubclass(cls, Module):
+ cls = type(__name__ + 'Class', (Module, ), {})
+ module = cls(module)
+ sys.modules[__name__] = module
+ return cls
+
+def define(**names):
+ cls = getClass()
+ for name, specifier in names.iteritems():
+ setattr(cls, name, Deferred(name, specifier))
+
+def deprecated(message, **names):
+ cls = getClass()
+ for name, specifier in names.iteritems():
+ setattr(cls, name, DeferredAndDeprecated(name, specifier, message))
+
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/deferredmodule.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/sample1.py.in
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/sample1.py.in 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/sample1.py.in 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1,16 @@
+import zope.deferredimport
+
+four = 4
+
+zope.deferredimport.define(
+ sample2 = 'zope.deferredimport.sample2',
+ one = 'zope.deferredimport.sample2:x',
+ two = 'zope.deferredimport.sample2:C.y',
+ )
+
+zope.deferredimport.deprecated(
+ "Will go away in 2007.",
+ three = 'zope.deferredimport.sample2:C',
+ )
+
+five = 5
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/sample1.py.in
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/sample2.py.in
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/sample2.py.in 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/sample2.py.in 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1,6 @@
+print "Sampe 2 imported!"
+
+x = 1
+
+class C:
+ y = 2
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/sample2.py.in
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope3/branches/jim-adapter/src/zope/deferredimport/tests.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/deferredimport/tests.py 2006-02-20 17:53:46 UTC (rev 41715)
+++ Zope3/branches/jim-adapter/src/zope/deferredimport/tests.py 2006-02-20 21:54:12 UTC (rev 41716)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+import os, re, shutil, sys, tempfile, unittest
+from zope.testing import doctest, renormalizing
+import zope.deferredimport
+
+class OutErr:
+
+ @staticmethod
+ def write(message):
+ sys.stdout.write(message)
+
+def setUp(test):
+ d = test.globs['tmp_d'] = tempfile.mkdtemp('deferredimport')
+ shutil.copy(
+ os.path.join(os.path.dirname(__file__), 'sample1.py.in'),
+ os.path.join(d, 'sample1.py'),
+ )
+ shutil.copy(
+ os.path.join(os.path.dirname(__file__), 'sample2.py.in'),
+ os.path.join(d, 'sample2.py'),
+ )
+ zope.deferredimport.__path__.append(d)
+ sys.modules.pop('zope.deferredimport.sample1', None)
+ sys.modules.pop('zope.deferredimport.sample2', None)
+
+ test.globs['oldstderr'] = sys.stderr
+ sys.stderr = OutErr
+
+def tearDown(test):
+ sys.stderr = test.globs['oldstderr']
+
+ zope.deferredimport.__path__.pop()
+ shutil.rmtree(test.globs['tmp_d'])
+ sys.modules.pop('zope.deferredimport.sample1', None)
+ sys.modules.pop('zope.deferredimport.sample2', None)
+
+def test_suite():
+ checker = renormalizing.RENormalizing((
+ (re.compile('.+/README.txt'), 'README.txt'),
+ ))
+ return doctest.DocFileSuite(
+ 'README.txt',
+ setUp=setUp, tearDown=tearDown,
+ optionflags=doctest.NORMALIZE_WHITESPACE,
+ checker=checker,
+ )
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: Zope3/branches/jim-adapter/src/zope/deferredimport/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the Zope3-Checkins
mailing list