[z3-checkins] r15153 - in z3/zopejam/trunk/src: zcmledit zopejam
hathawsh at codespeak.net
hathawsh at codespeak.net
Wed Jul 27 09:55:32 CEST 2005
Author: hathawsh
Date: Wed Jul 27 09:55:27 2005
New Revision: 15153
Modified:
z3/zopejam/trunk/src/zcmledit/configfile.py
z3/zopejam/trunk/src/zcmledit/directives.py
z3/zopejam/trunk/src/zcmledit/inspector.py
z3/zopejam/trunk/src/zcmledit/interfaces.py
z3/zopejam/trunk/src/zcmledit/project.py
z3/zopejam/trunk/src/zopejam/main.py
Log:
Made zcmledit aware of configuration contexts and "usedIn" attributes.
As a result, zcmledit can now understand grouping directives,
complex directives, and subdirectives.
Modified: z3/zopejam/trunk/src/zcmledit/configfile.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/configfile.py (original)
+++ z3/zopejam/trunk/src/zcmledit/configfile.py Wed Jul 27 09:55:27 2005
@@ -31,7 +31,6 @@
# used for including this config file
self.package_name = package_name
-
def load(self):
"""Parse the file into a tree of Elements.
@@ -77,22 +76,10 @@
finally:
f.close()
-
def createDirective(self, element):
"""Returns an IDirective to fit an XML element"""
ns, localname = element.name
-
- if localname == 'configure':
- t = directives.ConfigureDirective
- elif localname in ('include', 'includeOverrides'):
- t = directives.IncludeDirective
- elif ns == directives.meta_ns and localname in (
- 'directive', 'groupingDirective',
- 'complexDirective', 'simpleDirective'):
- t = directives.DefinitionDirective
- else:
- t = directives.CommonDirective
-
+ t = directives.get_directive_factory(ns, localname)
return t(element)
def getAbbreviatedFilename(self, trim_default=True):
Modified: z3/zopejam/trunk/src/zcmledit/directives.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/directives.py (original)
+++ z3/zopejam/trunk/src/zcmledit/directives.py Wed Jul 27 09:55:27 2005
@@ -13,8 +13,9 @@
from zcmledit.exceptions import NameResolutionError, NoPackageError
from zcmledit.exceptions import InvalidRelativeNameError, MissingPackageError
-meta_ns = u"http://namespaces.zope.org/meta"
+meta_ns = u'http://namespaces.zope.org/meta'
nzo_prefix = 'http://namespaces.zope.org/'
+default_config_context = 'zope.configuration.interfaces.IConfigurationContext'
class Directive(object):
@@ -63,14 +64,51 @@
return self._abs_package
return self.getInheritedPackageName()
+ def resolveNameAttribute(self, attr, required=False, default=None):
+ """Resolves a dotted name from an attribute"""
+ value = getattr(self, attr)
+ if value:
+ if value.startswith('.'):
+ try:
+ abs_package = self.getAbsolutePackageName()
+ return join_package(abs_package, value)
+ except NameResolutionError, e:
+ self.errors.append(
+ '%s: %s' % (e.__class__.__name__, str(e)))
+ return None
+ else:
+ return value
+ elif required:
+ self.errors.append("Missing attribute: '%s'" % attr)
+ return default
+
def getType(self):
- """Returns an IDefinitionDirective or None"""
- project = self.element.config_file.project
+ """Returns an IDefinitionDirective instance or None"""
+ if self.element.parent is not None:
+ parent_type = self.element.parent.directive.getType()
+ if parent_type is None:
+ # The parent directive has no definition
+ return None
+ context_iface_names, complex_parent = parent_type.getContextInfo()
+ else:
+ context_iface_names = [default_config_context]
+ complex_parent = None
if interfaces.IGenericNamespaceDirective.providedBy(self):
- ns, localname = self.element.name
- return project.definitions.get(('*', localname))
+ my_name = ('*', self.element.name[1])
else:
- return project.definitions.get(self.element.name)
+ my_name = self.element.name
+
+ # Find the definition most specific to the configuration context
+ project = self.element.config_file.project
+ for iface_name in context_iface_names:
+ iface = project.interfaces[iface_name]
+ inames = [iface_name] + [i.name for i in iface.sro]
+ for iname in inames:
+ key = (iname, complex_parent, my_name)
+ dfn = project.definitions.get(key)
+ if dfn is not None:
+ return dfn
+ return None
def getTypeName(self):
"""Returns a type name like 'http://namespaces.zope.org/zope:view'"""
@@ -192,6 +230,18 @@
def readElement(self):
self.errors = []
self.name = self.element.data.get('name')
+ self.used_in = self.element.data.get('used_in')
+ if self.name in ['configure', 'include', 'includeOverrides']:
+ # Although zope.configuration probably has no trouble with
+ # a directive that overloads these names, this package
+ # reads configuration files outside a configuration
+ # execution context. Without that context, it can only
+ # assume that these special names are never overloaded.
+ # The exception below tries to ensure the assumption
+ # never breaks.
+ raise RuntimeError(
+ "Unable to define directives named '%s' at this time."
+ % self.name)
self.schema = self.element.data.get('schema')
ns = None
@@ -205,26 +255,119 @@
if ns is None:
ns = self.element.data.get('namespace')
- self.fullname = (ns, self.name)
- if self.schema:
- if self.schema.startswith('.'):
- try:
- abs_package = self.getAbsolutePackageName()
- abs_schema = join_package(abs_package, self.schema)
- except NameResolutionError, e:
- abs_schema = None
- self.errors.append(
- '%s: %s' % (e.__class__.__name__, str(e)))
- else:
- abs_schema = self.schema
- else:
- self.errors.append("Missing 'schema' attribute")
- self.abs_schema = abs_schema
+ self.provided_name = (ns, self.name)
+ self.abs_schema = self.resolveNameAttribute('schema', required=True)
+ self.abs_used_in = self.resolveNameAttribute(
+ 'used_in', required=False, default=default_config_context)
def getSchemaInfo(self):
project = self.element.config_file.project
return project.interfaces[self.abs_schema]
+ def getContextInfo(self):
+ """Returns directive context information.
+
+ Used for discovering the type of a contained directive.
+ Returns (context_interface_names, complex_directive_name).
+ """
+ # a non-grouping directive should not contain any directives,
+ # so return empty context information.
+ return ([], None)
+
+ def getProvidedName(self):
+ """Returns the name of the provided directive as a tuple"""
+ return self.provided_name
+
+ def getDefinitionKey(self):
+ """Returns the key for this directive in project.definitions.
+
+ The key is a tuple: (used_in, complex_parent_name, provided_name).
+ """
+ return (self.abs_used_in, None, self.provided_name)
+
+ def getRequiredInterfaceNames(self):
+ """Returns the interface names this definition depends upon"""
+ res = []
+ if self.abs_schema:
+ res.append(self.abs_schema)
+ if self.abs_used_in:
+ res.append(self.abs_used_in)
+ return res
+
+ def getRequiredClassNames(self):
+ """Returns the class names this definition depends upon"""
+ return []
+
+
+class ComplexDefinitionDirective(DefinitionDirective):
+ """A complexDirective."""
+ implements(interfaces.IComplexDefinitionDirective)
+
+ context_iface = 'zope.configuration.config.IComplexDirectiveContext'
+
+ def getRequiredInterfaceNames(self):
+ """Returns the class names this definition depends upon"""
+ base = super(ComplexDefinitionDirective, self)
+ return base.getRequiredInterfaceNames() + [self.context_iface]
+
+ def getContextInfo(self):
+ """Returns directive context information.
+
+ Used for discovering the type of a contained directive.
+ Returns (context_interface_names, complex_directive_name).
+ """
+ return ([self.context_iface], self.getProvidedName())
+
+
+class SubdirectiveDefinitionDirective(DefinitionDirective):
+ """A subdirective."""
+ def readElement(self):
+ super(SubdirectiveDefinitionDirective, self).readElement()
+
+ self.complex_parent_name = None
+ parent = self.element.parent
+ icomplex = interfaces.IComplexDefinitionDirective
+ if parent is None or not icomplex.providedBy(parent.directive):
+ self.errors.append(
+ 'subdirective defined outside a complexDirective')
+ else:
+ self.complex_parent_name = parent.directive.getProvidedName()
+
+ def getDefinitionKey(self):
+ """Returns the key for this directive in project.definitions.
+
+ The key is a tuple: (used_in, complex_parent_name, provided_name).
+ """
+ return (self.abs_used_in, self.complex_parent_name, self.provided_name)
+
+
+class GroupingDefinitionDirective(DefinitionDirective):
+ """A groupingDirective."""
+ def readElement(self):
+ super(GroupingDefinitionDirective, self).readElement()
+ self.handler = self.element.data.get('handler')
+ self.abs_handler = self.resolveNameAttribute('handler', required=True)
+
+ def getRequiredClassNames(self):
+ """Returns the class names this definition depends upon"""
+ if self.abs_handler:
+ return [self.abs_handler]
+ return []
+
+ def getContextInfo(self):
+ """Returns directive context information.
+
+ Used for discovering the type of a contained directive.
+ Returns (context_interface_names, complex_directive_name).
+ """
+ if self.abs_handler:
+ project = self.element.config_file.project
+ class_info = project.classes[self.abs_handler]
+ impl = class_info.implements_names
+ return (list(impl), None)
+ else:
+ return ([], None)
+
class BootstrapDirective(Directive):
"""A bootstrap definition directive.
@@ -233,15 +376,17 @@
"""
implements(interfaces.IDefinitionDirective)
- def __init__(self, project, ns, name, abs_schema):
+ def __init__(self, project, ns, name, abs_schema,
+ usedIn=default_config_context):
self.project = project
self.element = None
self.errors = ()
self.name = name
- self.fullname = (ns, name)
+ self.provided_name = (ns, name)
self.schema = abs_schema
self.abs_schema = abs_schema
+ self.abs_used_in = usedIn
def getAbsolutePackageName(self):
return None
@@ -249,22 +394,96 @@
def getSchemaInfo(self):
return self.project.interfaces[self.abs_schema]
+ def getProvidedName(self):
+ """Returns the name of the provided directive as a tuple"""
+ return self.provided_name
+
+ def getDefinitionKey(self):
+ """Returns the key for this directive in project.definitions.
+
+ The key is a tuple: (used_in, complex_parent_name, provided_name).
+ """
+ return (default_config_context, None, self.provided_name)
+
+ def getRequiredInterfaceNames(self):
+ """Returns the interface names this definition depends upon"""
+ return [self.abs_schema]
+
+ def getRequiredClassNames(self):
+ """Returns the class names this definition depends upon"""
+ return []
+
+ def getType(self):
+ raise NotImplementedError
+
def getTypeName(self):
"""Returns a type name like 'http://namespaces.zope.org/zope:view'"""
- return '%s:%s' % self.fullname
+ return nzo_prefix + 'meta:directive'
def getAbbreviatedTypeName(self):
"""Returns a shortened directive type name like 'zope:view'"""
- name = self.getTypeName()
- if name.startswith(nzo_prefix):
- name = name[len(nzo_prefix):]
- return name
+ return 'meta:directive'
+
+
+class BootstrapGroupingDirective(BootstrapDirective):
+ """A bootstrap grouping definition directive."""
+
+ def __init__(self, project, ns, name, abs_schema, abs_handler,
+ usedIn=default_config_context):
+ super(BootstrapGroupingDirective, self).__init__(
+ project, ns, name, abs_schema, usedIn=usedIn)
+ self.abs_handler = abs_handler
+
+ def getRequiredClassNames(self):
+ """Returns the class names this definition depends upon"""
+ return [self.abs_handler]
+
+ def getContextInfo(self):
+ """Returns directive context information.
+
+ Used for discovering the type of a contained directive.
+ Returns (context_interface_names, complex_directive_name).
+ """
+ class_info = self.project.classes[self.abs_handler]
+ impl = class_info.implements_names
+ return (list(impl), None)
+
+ def getType(self):
+ raise NotImplementedError
+
+ def getTypeName(self):
+ """Returns a type name like 'http://namespaces.zope.org/zope:view'"""
+ return nzo_prefix + 'meta:groupingDirective'
+
+ def getAbbreviatedTypeName(self):
+ """Returns a shortened directive type name like 'zope:view'"""
+ return 'meta:groupingDirective'
class CommonDirective(Directive):
implements(interfaces.IDirective)
+meta_factories = {
+ 'directive': DefinitionDirective,
+ 'groupingDirective': GroupingDefinitionDirective,
+ 'complexDirective': ComplexDefinitionDirective,
+ 'subdirective': SubdirectiveDefinitionDirective,
+ }
+
+
+def get_directive_factory(ns, localname):
+ if localname == 'configure':
+ return ConfigureDirective
+ elif localname in ('include', 'includeOverrides'):
+ return IncludeDirective
+ elif ns == meta_ns:
+ t = meta_factories.get(localname)
+ if t is not None:
+ return t
+ return CommonDirective
+
+
def join_package(parent, child):
"""Joins an absolute package name with a relative object name."""
if child == '.':
Modified: z3/zopejam/trunk/src/zcmledit/inspector.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/inspector.py (original)
+++ z3/zopejam/trunk/src/zcmledit/inspector.py Wed Jul 27 09:55:27 2005
@@ -13,14 +13,34 @@
import cPickle
import os
import sys
+from types import ClassType
+from zope.interface import implementedBy
from zope.interface.interfaces import IInterface
_import_chickens = {}, {}, ("*",) # dead chickens needed by __import__
-def inspect_interfaces(names):
- """Returns {name: {'doc', 'bases', 'sro', 'attrs' | 'error'}}"""
+def inspect_globals(class_names, iface_names):
+ """Returns information about named classes and interfaces."""
+ classes = inspect_classes(class_names)
+
+ # also inspect the interfaces implemented by the class
+ iface_names = list(iface_names) # make a copy
+ for class_info in classes.values():
+ names = class_info.get('implements')
+ if names:
+ iface_names.extend(names)
+
+ ifaces = inspect_interfaces(iface_names)
+ return (classes, ifaces)
+
+
+def inspect_classes(names):
+ """Returns information about named classes.
+
+ Returns {name: {'doc','bases','mro','implements','attributes'|'error'}}
+ """
res = {}
# the names are absolute.
todo = list(names)
@@ -31,55 +51,127 @@
info = {}
res[name] = info
- pos = name.rfind('.')
- if pos >= 0:
- mname = name[:pos]
- oname = name[pos + 1:]
- else:
- mname = ''
- oname = name
+ try:
+ obj = import_name(name)
+ except:
+ info['error'] = str(sys.exc_info()[1])
+ continue
+
+ info['doc'] = getattr(obj, '__doc__', None)
+
+ if not isinstance(obj, (type, ClassType)):
+ info['error'] = "'%s' is not a class" % name
+ continue
+
+ # report implemented interfaces
+ impl = []
+ for iface in implementedBy(obj):
+ fullname = get_name(iface)
+ if fullname:
+ impl.append(fullname)
+ info['implements'] = impl
+
+ # report base classes
+ bases = []
+ for base in getattr(obj, '__bases__', ()):
+ fullname = get_name(base)
+ if fullname:
+ bases.append(fullname)
+ if not res.has_key(fullname):
+ todo.append(fullname)
+ info['bases'] = bases
+
+ # report method resolution order
+ mro = []
+ for base in getattr(obj, '__mro__', ()):
+ fullname = get_name(base)
+ if fullname:
+ mro.append(fullname)
+ info['mro'] = mro
+
+ attrs = {}
+ for n in getattr(obj, '__dict__', {}).keys():
+ if hasattr(obj, n):
+ attr = getattr(obj, n)
+ ainfo = {'doc': getattr(attr, '__doc__', None)}
+ attrs[n] = ainfo
+ info['attributes'] = attrs
+ return res
+
+
+def inspect_interfaces(names):
+ """Returns information about named interfaces.
+
+ Returns {name: {'doc', 'bases', 'sro', 'attributes' | 'error'}}
+ """
+ res = {}
+ # the names are absolute.
+ todo = list(names)
+ while todo:
+ name = todo.pop()
+ if res.has_key(name):
+ continue
+ info = {}
+ res[name] = info
try:
- module = __import__(mname, *_import_chickens)
- obj = getattr(module, oname)
+ obj = import_name(name)
except:
info['error'] = str(sys.exc_info()[1])
continue
- if IInterface.providedBy(obj):
- info['doc'] = getattr(obj, '__doc__', None)
+ if not IInterface.providedBy(obj):
+ info['error'] = "'%s' is not an interface" % name
+ continue
- # report base interfaces
- bases = []
- for base in getattr(obj, '__bases__', ()):
- m = getattr(base, '__module__', None)
- n = getattr(base, '__name__', None)
- if m and n:
- fullname = '%s.%s' % (m, n)
- bases.append(fullname)
- if not res.has_key(fullname):
- todo.append(fullname)
- info['bases'] = bases
-
- # report specification resolution order
- sro = []
- for base in getattr(obj, '__sro__', ()):
- m = getattr(base, '__module__', None)
- n = getattr(base, '__name__', None)
- if m and n:
- fullname = '%s.%s' % (m, n)
- sro.append(fullname)
- info['sro'] = sro
-
- attrs = {}
- for n in obj.names(False):
- attrs[n] = obj[n]
- info['attributes'] = attrs
- else:
- info['error'] = 'not an interface; type is %s' % str(type(obj))
+ info['doc'] = getattr(obj, '__doc__', None)
+
+ # report base interfaces
+ bases = []
+ for base in getattr(obj, '__bases__', ()):
+ fullname = get_name(base)
+ if fullname:
+ bases.append(fullname)
+ if not res.has_key(fullname):
+ todo.append(fullname)
+ info['bases'] = bases
+
+ # report specification resolution order
+ sro = []
+ for base in getattr(obj, '__sro__', ()):
+ fullname = get_name(base)
+ if fullname:
+ sro.append(fullname)
+ info['sro'] = sro
+
+ attrs = {}
+ for n in obj.names(False):
+ attrs[n] = obj[n]
+ info['attributes'] = attrs
return res
+def import_name(name):
+ pos = name.rfind('.')
+ if pos >= 0:
+ mname = name[:pos]
+ oname = name[pos + 1:]
+ else:
+ mname = ''
+ oname = name
+
+ module = __import__(mname, *_import_chickens)
+ return getattr(module, oname)
+
+
+def get_name(obj):
+ m = getattr(obj, '__module__', None)
+ n = getattr(obj, '__name__', None)
+ if m and n:
+ return '%s.%s' % (m, n)
+ return None
+
+
def main():
# pickle in, pickle out.
funcname, args, kwargs = cPickle.load(sys.stdin)
Modified: z3/zopejam/trunk/src/zcmledit/interfaces.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/interfaces.py (original)
+++ z3/zopejam/trunk/src/zcmledit/interfaces.py Wed Jul 27 09:55:27 2005
@@ -17,5 +17,8 @@
class IDefinitionDirective(IDirective):
pass
+class IComplexDefinitionDirective(IDefinitionDirective):
+ pass
+
class IProject(Interface):
pass
Modified: z3/zopejam/trunk/src/zcmledit/project.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/project.py (original)
+++ z3/zopejam/trunk/src/zcmledit/project.py Wed Jul 27 09:55:27 2005
@@ -33,37 +33,116 @@
pythonpath = [os.path.join(self.base, 'src')] + sys.path
self.pythonpath = pythonpath
- def createBootstrapDirectives(self):
- """Returns a dictionary containing the bootstrap definitions"""
- res = {}
- meta_ns = directives.meta_ns
- for ns, name, schema in [
- ('*', 'configure',
- "zope.configuration.zopeconfigure.IZopeConfigure"),
- ('*', 'include', "zope.configuration.xmlconfig.IInclude"),
- ('*', 'includeOverrides', "zope.configuration.xmlconfig.IInclude"),
- (meta_ns, 'directive',
- "zope.configuration.config.IFullInfo"),
- (meta_ns, 'groupingDirective',
- "zope.configuration.config.IFullInfo"),
- (meta_ns, 'directives',
- "zope.configuration.config.IDirectivesInfo"),
- (meta_ns, 'complexDirective',
- "zope.configuration.config.IFullInfo"),
- (meta_ns, 'subdirective',
- "zope.configuration.config.IDirectiveInfo"),
- (meta_ns, 'provides',
- "zope.configuration.config.IProvidesDirectiveInfo"),
- ]:
- res[(ns, name)] = directives.BootstrapDirective(
- self, ns, name, schema)
- return res
+ def createBootstrapDefinitions(self):
+ """fills self.directives with the bootstrap definition directives"""
+
+ self.definitions = {}
+ # self.directives contains:
+ # {definition_key: IDirectiveDefinition}
+ # where definition_key == (used_in, complex_parent, provided_name).
+ # complex_parent and provided_name each contain (ns, localname),
+ # although complex_parent is None except when defining a
+ # subdirective. used_in is an interface name.
+
+ def defineGeneric(name, schema):
+ d = directives.BootstrapDirective(
+ self, '*', name, schema)
+ self.definitions[d.getDefinitionKey()] = d
+
+ def defineGroupingGeneric(name, schema, handler_class):
+ d = directives.BootstrapGroupingDirective(
+ self, '*', name, schema, handler_class)
+ self.definitions[d.getDefinitionKey()] = d
+
+ def defineDirective(
+ name, schema, usedIn=directives.default_config_context):
+ ns = directives.meta_ns
+ d = directives.BootstrapDirective(
+ self, ns, name, schema, usedIn=usedIn)
+ self.definitions[d.getDefinitionKey()] = d
+
+ def defineGroupingDirective(
+ name, schema, handler_class,
+ usedIn=directives.default_config_context):
+ ns = directives.meta_ns
+ d = directives.BootstrapGroupingDirective(
+ self, ns, name, schema, handler_class, usedIn=usedIn)
+ self.definitions[d.getDefinitionKey()] = d
+
+ module = 'zope.configuration.config'
+
+ # The following initialization is based on
+ # zope.configuration.xmlconfig.registerCommonDirectives().
+
+ defineGroupingGeneric(
+ 'configure',
+ 'zope.configuration.zopeconfigure.IZopeConfigure',
+ 'zope.configuration.zopeconfigure.ZopeConfigure')
+
+ defineGeneric(
+ 'include',
+ 'zope.configuration.xmlconfig.IInclude')
+
+ defineGeneric(
+ 'includeOverrides',
+ 'zope.configuration.xmlconfig.IInclude')
+
+ # The following initialization is based on
+ # zope.configuration.config._bootstrap().
+
+ # Define the directive (simple directive) directive
+ defineDirective(
+ 'directive',
+ module + '.IStandaloneDirectiveInfo')
+
+ # Standalone groupingDirective
+ defineDirective(
+ 'groupingDirective',
+ module + '.IStandaloneDirectiveInfo')
+
+ # define the directives directive
+ defineGroupingDirective(
+ 'directives',
+ module + '.IDirectivesInfo',
+ module + '.DirectivesHandler')
+
+ # directive and groupingDirective inside directives
+ defineDirective(
+ 'directive',
+ module + '.IFullInfo',
+ usedIn = module + '.IDirectivesContext')
+ defineDirective(
+ 'groupingDirective',
+ module + '.IFullInfo',
+ usedIn = module + '.IDirectivesContext')
+
+ # Set up complex directive directive, both standalone, and in
+ # directives directive
+ defineGroupingDirective(
+ 'complexDirective',
+ module + '.IStandaloneDirectiveInfo',
+ module + '.ComplexDirectiveDefinition')
+ defineGroupingDirective(
+ 'complexDirective',
+ module + '.IFullInfo',
+ module + '.ComplexDirectiveDefinition',
+ usedIn = module + '.IDirectivesContext')
+
+ # Finally, set up subdirective directive
+ defineDirective(
+ 'subdirective',
+ module + '.IDirectiveInfo',
+ usedIn = module + '.IComplexDirectiveContext')
+
+ # meta:provides
+ defineDirective(
+ 'provides',
+ module + '.IProvidesDirectiveInfo')
def load(self):
+ self.createBootstrapDefinitions()
self.packages = {} # {package name: [filename]}
self.files = {} # {filename: config_file}
- # self.definitions contains {(ns, localname): IDirectiveDefinition}
- self.definitions = self.createBootstrapDirectives()
self.root_config = ConfigurationFile(self, self.root_filename)
self.files[self.root_filename] = self.root_config
@@ -90,21 +169,41 @@
# add to self.definitions
for dfn in cfg.definitions:
- if self.definitions.has_key(dfn.fullname):
- raise RuntimeError("can't handle multiple definitions for "
- "directive %s" % repr(dfn.fullname))
- self.definitions[dfn.fullname] = dfn
-
- self.load_schemas()
-
- def load_schemas(self):
- names = [dfn.abs_schema for dfn in self.definitions.values()]
- d = self.call_inspector('inspect_interfaces', names)
+ key = dfn.getDefinitionKey()
+ if self.definitions.has_key(key):
+ # Conflicting metadirectives.
+ # Panic for now, but in the future, this could
+ # instead set an error on the existing directive.
+ raise RuntimeError(
+ 'metadirective conflict on %s' % repr(key))
+ self.definitions[key] = dfn
+
+ self.load_globals()
+
+ def load_globals(self):
+ """Fill self.interfaces and self.classes"""
+ class_names = set()
+ iface_names = set()
+ iface_names.add(directives.default_config_context)
+
+ for dfn in self.definitions.values():
+ class_names.update(dfn.getRequiredClassNames())
+ iface_names.update(dfn.getRequiredInterfaceNames())
+
+ c, i = self.call_inspector(
+ 'inspect_globals', list(class_names), list(iface_names))
+
+ self.classes = {}
self.interfaces = {}
- for name, info in d.items():
+ for name, info in c.items():
+ self.classes[name] = ClassInfo(name, info)
+ for name, info in i.items():
self.interfaces[name] = InterfaceInfo(name, info)
+
for info in self.interfaces.values():
info.initBases(self.interfaces)
+ for info in self.classes.values():
+ info.initBases(self.classes, self.interfaces)
def call_inspector(self, funcname, *args, **kw):
inspector_py = os.path.join(here, 'inspector.py')
@@ -148,6 +247,28 @@
return p
+class ClassInfo:
+ """Contains info received from inspector.inspect_classes()."""
+
+ def __init__(self, name, info):
+ self.name = name
+ self.error = info.get('error', '')
+ self.doc = info.get('doc', '')
+ self.implements_names = info.get('implements', ())
+ self.base_names = info.get('bases', ())
+ self.mro_names = info.get('mro', ())
+ self.attributes = info.get('attributes')
+ if self.attributes is None:
+ self.attributes = {}
+
+ def initBases(self, all_classes, all_interfaces):
+ """As part of construction, link with base objects."""
+ self.bases = [all_classes[name] for name in self.base_names]
+ self.mro = [all_classes[name] for name in self.mro_names]
+ self.implements = [all_interfaces[name]
+ for name in self.implements_names]
+
+
class InterfaceInfo:
"""Contains info received from inspector.inspect_interfaces()."""
@@ -166,7 +287,7 @@
self.fields[k] = FieldInfo(self, k, v)
def initBases(self, all_interfaces):
- """As part of construction, link with base InterfaceInfo objects."""
+ """As part of construction, link with base objects."""
self.bases = [all_interfaces[name] for name in self.base_names]
self.sro = [all_interfaces[name] for name in self.sro_names]
Modified: z3/zopejam/trunk/src/zopejam/main.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/main.py (original)
+++ z3/zopejam/trunk/src/zopejam/main.py Wed Jul 27 09:55:27 2005
@@ -25,7 +25,7 @@
here = os.path.abspath(os.path.dirname(__file__))
-add_menu_ids = {} # {id -> (ns, localname)}
+add_menu_ids = {} # {id -> definition_key}
class PaletteImageList(wx.ImageList):
@@ -289,33 +289,33 @@
# create reverse_menu_ids from add_menu_ids
reverse_menu_ids = {}
- for item_id, fullname in add_menu_ids.items():
- reverse_menu_ids[fullname] = item_id
+ for item_id, key in add_menu_ids.items():
+ reverse_menu_ids[key] = item_id
# figure out what should go in the add menu
- options = {} # {(label, namespace): [(localname, item_id)]}
- for fullname in self.project.definitions.keys():
- item_id = reverse_menu_ids.get(fullname)
+ submenus = {} # {(label, namespace): [(localname, item_id)]}
+ for key, dfn in self.project.definitions.items():
+ item_id = reverse_menu_ids.get(key)
if item_id is None:
item_id = wx.NewId()
- reverse_menu_ids[fullname] = item_id
- add_menu_ids[item_id] = fullname
- ns, localname = fullname
+ reverse_menu_ids[key] = item_id
+ add_menu_ids[item_id] = key
+ ns, localname = dfn.getProvidedName()
if ns.startswith(nzo_prefix):
label = ns[len(nzo_prefix):]
else:
label = ns
- key = (label, ns)
- names = options.get(key)
+ submenu = (label, ns)
+ names = submenus.get(submenu)
if names is None:
names = []
- options[key] = names
+ submenus[submenu] = names
names.append((localname, item_id))
- # add the options to the add menu
- options = options.items()
- options.sort()
- for (label, ns), names in options:
+ # add the submenus to the add menu
+ submenus = submenus.items()
+ submenus.sort()
+ for (label, ns), names in submenus:
m = wx.Menu()
names.sort()
for name, item_id in names:
@@ -326,16 +326,16 @@
def onMenuHighlight(self, event):
item_id = event.GetId()
if item_id > 0:
- fullname = add_menu_ids.get(item_id)
+ key = add_menu_ids.get(item_id)
else:
- fullname = None
- if not fullname:
+ key = None
+ if not key:
# hide the tip soon
if not self.tip_hide_timer.IsRunning():
self.tip_hide_timer.Start(300, wx.TIMER_ONE_SHOT)
return
- dfn = self.project.definitions[fullname]
+ dfn = self.project.definitions[key]
info = dfn.getSchemaInfo()
if info.error:
doc = ('An error occurred while loading the '
@@ -347,7 +347,7 @@
if not doc:
doc = 'No documentation available.'
- ns, localname = fullname
+ ns, localname = dfn.getProvidedName()
if ns.startswith(nzo_prefix):
label = ns[len(nzo_prefix):]
else:
@@ -561,7 +561,7 @@
state = self.GetItemState(i, mask)
if state:
flags[directive_index] = state
-
+
# _col and _colSortFlag are defined in ColumnSorterMixin.
# col is the column which was clicked on and
# sf, the sort flag, is False for descending (Z->A)
More information about the z3-checkins
mailing list