[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