[Zope-Checkins] CVS: Zope3/lib/python/Zope/Configuration - meta.py:1.1.2.8 name.py:1.1.2.10 xmlconfig.py:1.1.2.11

Jim Fulton jim@zope.com
Tue, 26 Mar 2002 19:47:16 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Configuration
In directory cvs.zope.org:/tmp/cvs-serv28160/lib/python/Zope/Configuration

Modified Files:
      Tag: Zope-3x-branch
	meta.py name.py xmlconfig.py 
Log Message:
Merged in changes from contextual-directives branch.

Now, a leading dot in a dotted name implies the package the include
file was included from. It still defaults to ZopeProducts if a file 
was not included via a package.

A few of the config files have been convered to use the
shorthand. The rest still can be converted.

I also checked this against Step 6 in the tutorial, which I will check
in in a moment.


=== Zope3/lib/python/Zope/Configuration/meta.py 1.1.2.7 => 1.1.2.8 ===
 from ConfigurationDirectiveInterfaces import INonEmptyDirective
 from ConfigurationDirectiveInterfaces import ISubdirectiveHandler
-from name import resolve
 
 
 _directives = {}
@@ -34,15 +33,15 @@
     directives[name] = subdirs
     return subdirs
 
-def _exe(callable, subs, kw):
-    r = callable(**kw)
+def _exe(callable, subs, context, kw):
+    r = callable(context, **kw)
 
     if subs or INonEmptyDirective.isImplementedBy(callable):
         return r, subs
     else:
         return lambda: r, subs
 
-def begin(_custom_directives, _name, **kw):
+def begin(_custom_directives, _name, _context, **kw):
     if _custom_directives and (_name in _custom_directives):
         callable, subs = _custom_directives[_name]
     else:
@@ -51,9 +50,9 @@
         except KeyError:
             raise InvalidDirective(_name)
 
-    return _exe(callable, subs, kw)
+    return _exe(callable, subs, _context, kw)
 
-def sub(subs, _name, **kw):
+def sub(subs, _name, _context, **kw):
 
     base, subdirs = subs
     
@@ -64,7 +63,7 @@
 
     callable = getattr(base, _name[1])
 
-    return _exe(callable, subs, kw)
+    return _exe(callable, subs, _context, kw)
 
 defaultkw = ({},)
 def end(base):
@@ -80,19 +79,20 @@
 
 class DirectiveNamespace:
 
-    def __init__(self, namespace):
+    def __init__(self, _context, namespace):
         self._namespace = namespace
 
-    def directive(self, name, handler, attributes='', namespace=None):
+    def directive(self, _context, name, handler, attributes='',
+                  namespace=None):
         namespace = namespace or self._namespace
-        subs = register((namespace, name), resolve(handler))
+        subs = register((namespace, name), _context.resolve(handler))
         return Subdirective(subs, namespace)
 
     def __call__(self):
         return ()
 
-def Directive(namespace, name, handler, attributes=''):
-    subs = register((namespace, name), resolve(handler))
+def Directive(_context, namespace, name, handler, attributes=''):
+    subs = register((namespace, name), _context.resolve(handler))
     return Subdirective(subs, namespace)
 
 Directive.__implements__ = INonEmptyDirective
@@ -114,7 +114,7 @@
         self._subs = subs
         self._namespace = namespace
 
-    def subdirective(self, name, attributes='', namespace=None):
+    def subdirective(self, _context, name, attributes='', namespace=None):
         namespace = namespace or self._namespace
         if not namespace:
             raise InvaliDirectiveDefinition(name)


=== Zope3/lib/python/Zope/Configuration/name.py 1.1.2.9 => 1.1.2.10 ===
 from types import ModuleType
 
-def resolve(name, _silly=('__doc__',), _globals={}):
+def resolve(name, package='ZopeProducts', _silly=('__doc__',), _globals={}):
     if name.startswith('.'):
-        name='ZopeProducts'+name
+        name=package+name
 
-    if name.endswith('.'):
+    if name.endswith('.') or name.endswith('+'):
         name = name[:-1]
         repeat = 1
     else:


=== Zope3/lib/python/Zope/Configuration/xmlconfig.py 1.1.2.10 => 1.1.2.11 ===
     __top_name = 'http://namespaces.zope.org/zope', 'zopeConfigure' 
 
-    def __init__(self, actions, level=None, directives=None):
+    def __init__(self, actions, context, directives=None):
         self.__stack = []
-        self.__level = level
         self.__actions = actions
         self.__directives = directives
+        self.__context = context
+        context.resolve
 
     def setDocumentLocator(self, locator):
         self.__locator=locator
@@ -85,7 +86,8 @@
 
         if len(stack) == 1:
             try:                
-                stack.append(begin(self.__directives, name, **kw))
+                stack.append(begin(self.__directives, name, self.__context,
+                                   **kw))
             except Exception, v:
                 raise ZopeXMLConfigurationError, (
                     self.__locator, v), sys.exc_info()[2] 
@@ -96,7 +98,7 @@
                 raise ZopeXMLConfigurationError(self.__locator,
                                                 'Invalid sub-directive')
             try:
-                stack.append(sub(subs, name, **kw))
+                stack.append(sub(subs, name, self.__context, **kw))
             except Exception, v:
                 raise ZopeXMLConfigurationError, (
                     self.__locator, v), sys.exc_info()[2] 
@@ -117,7 +119,7 @@
 
         try:
             for des, callable, args, kw in actions:
-                append((self.__level,
+                append((self.__context,
                         (self.__locator.getLineNumber(),
                          self.__locator.getColumnNumber(),
                          self.__locator.getSystemId(),
@@ -141,16 +143,35 @@
         and% at line %s column %s of %s
         """ % ((self.des,) + self.l1 + self.l2)
 
-def xmlconfig(file, actions=None, level=None, directives=None):
+class Context:
+    def __init__(self, stack, module=None):
+        self.__stackcopy = tuple(stack)
+        if module is None:
+            self.__package = 'ZopeProducts'
+        else:
+            self.__package = module.__name__
+
+    def _stackcopy(self):
+        return self.__stackcopy
+
+    def resolve(self, dottedname):
+        return name.resolve(dottedname, self.__package)
+
+
+def xmlconfig(file, actions=None, context=None, directives=None):
+    if context is None:
+        context = name
+
     if actions is None:
-        call=actions=[]
+        call = actions = []
     else:
-        call=0
+        call = 0
     
-    src=InputSource(getattr(file, 'name', '<string>'))
+    src = InputSource(getattr(file, 'name', '<string>'))
     src.setByteStream(file)
-    parser=make_parser()
-    parser.setContentHandler(ConfigurationHandler(actions, level, directives))
+    parser = make_parser()
+    parser.setContentHandler(ConfigurationHandler(actions, context,
+                                                  directives))
     parser.setFeature(feature_namespaces, 1)
     parser.parse(src)
 
@@ -160,7 +181,7 @@
             if des in descriptors:
                 raise ZopeConflictingConfigurationError(
                     descriptors[des], loc, des) 
-            descriptors[des]=loc
+            descriptors[des] = loc
             callable(*args, **kw)
             
 class ZopeConfigurationConflictError(ZopeXMLConfigurationError):
@@ -186,22 +207,22 @@
 
         f = open(file_name)
         self._stack=[file_name]
-        xmlconfig(f, self._actions, tuple(self._stack), self._directives)
+        xmlconfig(f, self._actions, Context(self._stack), self._directives)
         f.close()
 
-    def include(self, file, package=None):
+    def include(self, _context, file, package=None):
         if package is not None:
             try:
-                module = name.resolve(package)
-                if len(module.__path__) != 1:
+                package = _context.resolve(package)
+                if len(package.__path__) != 1:
                     print ("Module Path: '%s' has wrong number of elements"
-                            % str(module.__path__))
+                            % str(package.__path__))
                 # XXX: This should work for 99% of cases
                 # We may want to revisit this with a more robust
                 # mechanism later. Specifically, sometimes __path__
                 # will have more than one element. Also, we could
-                # use module.__file__, and lop the tail off that.
-                prefix = module.__path__[0]
+                # use package.__file__, and lop the tail off that.
+                prefix = package.__path__[0]
             except (ImportError, AttributeError, ValueError):
                 raise ValueError, "Invalid package attribute: %s" % package
         else:
@@ -211,7 +232,8 @@
 
         f = open(file_name)
         self._stack.append(file_name)
-        xmlconfig(f, self._actions, tuple(self._stack), self._directives)
+        xmlconfig(f, self._actions, Context(self._stack, package),
+                  self._directives)
         self._stack.pop()
         f.close()
         return ()
@@ -227,9 +249,9 @@
         # organize actions by discriminators
         unique = {}
         for i in range(len(actions)):
-            path, loc, des, callable, args, kw = actions[i]
+            context, loc, des, callable, args, kw = actions[i]
             a = unique.setdefault(des, [])
-            a.append((path, i, loc, (callable, args, kw)))
+            a.append((context._stackcopy(), i, loc, (callable, args, kw)))
 
         # Check for conflicts
         conflicts = {}