[Zope3-checkins] CVS: Zope3/src/zope/configuration -
docutils.py:1.1 stxdocs.py:1.1 config.py:1.14
Stephan Richter
srichter at cosmos.phy.tufts.edu
Thu Jan 22 18:53:16 EST 2004
Update of /cvs-repository/Zope3/src/zope/configuration
In directory cvs.zope.org:/tmp/cvs-serv6835/zope/configuration
Modified Files:
config.py
Added Files:
docutils.py stxdocs.py
Log Message:
Implemented new ZCML doc generator.
I modified config.py so that some meta-data information is recorded that is
documentation generation friendly. I added a method 'document()' to the
Configuration machine to support that. The 'document()' method actually
collects information that was lost before.
stxdocs.py creates the documentation in STX format. Each directive and its
subdirectives go into one file. Each namespace is a directory.
docutils.py contains some helper functions that might be useful for other
doc generators (like RNG XML Schema and LaTeX).
=== Added File Zope3/src/zope/configuration/docutils.py ===
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Helper Utility to wrap a text to a set width of characters
$Id: docutils.py,v 1.1 2004/01/22 23:53:15 srichter Exp $
"""
import re
para_sep = re.compile('\n{2,}')
whitespace=re.compile('[ \t\n\r]+')
def wrap(text, width=78, indent=0):
""" """
paras = para_sep.split(text.strip())
new_paras = []
for par in paras:
words= filter(None, whitespace.split(par))
lines = []
line = []
length = indent
for word in words:
if length + len(word) + 1 <= width:
line.append(word)
length += len(word) + 1
else:
lines.append(' '*indent + ' '.join(line))
line = []
length = indent
lines.append(' '*indent + ' '.join(line))
new_paras.append('\n'.join(lines))
return '\n\n'.join(new_paras) + '\n\n'
def makeDocStructures(context):
""" """
namespaces = {}
subdirs = {}
for (namespace, name), schema, usedIn, info, parent in context._docRegistry:
if not parent:
ns_entry = namespaces.setdefault(namespace, {})
ns_entry[name] = (schema, info)
else:
sd_entry = subdirs.setdefault((parent.namespace, parent.name), [])
sd_entry.append((namespace, name, schema, info))
return namespaces, subdirs
=== Added File Zope3/src/zope/configuration/stxdocs.py ===
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""STX Configuration Documentation Renderer
Usage: stxdocs.py [options]
Options:
-h / --help
Print this message and exit.
-f <path>
Specifies the root ZCML meta directives file, relative to the current
location. All included files will be considered as well
-o <dir>
Specifies a directory, relative to the current location in which the
documentation is stored. Note that this tool will create
sub-directories with files in them.
$Id: stxdocs.py,v 1.1 2004/01/22 23:53:15 srichter Exp $
"""
import sys, os, getopt
import zope
from zope.schema import getFieldsInOrder
from zope.configuration import config, xmlconfig
from zope.configuration.docutils import wrap, makeDocStructures
def usage(code, msg=''):
# Python 2.1 required
print >> sys.stderr, __doc__
if msg:
print >> sys.stderr, msg
sys.exit(code)
def _directiveDocs(name, schema, info, indent_offset=0):
"""Generate the documentation for one directive."""
# Write out the name of the directive
text = ' '*indent_offset
text += '%s\n\n' %name
# Specify the file and location it has been declared
if isinstance(info, xmlconfig.ParserInfo):
# We do not want to specify the whole path; starting at the 'zope'
# package is enough.
base_dir = os.path.split(zope.__file__)[0][:-4]
file = info.file.replace(base_dir, '')
info_text = 'File %s, lines %i - %i.' %(file, info.line, info.eline)
text += wrap(info_text, 78, indent_offset+2)
elif isinstance(info, (str, unicode)) and info:
text += wrap(info, 78, indent_offset+2)
# Use the schema documentation string as main documentation text for the
# directive.
text += wrap(schema.getDoc(), 78, indent_offset+2)
text += ' '*indent_offset + ' Attributes\n\n'
# Create directive attribute documentation
for name, field in getFieldsInOrder(schema):
name = name.strip('_')
if field.required:
opt = 'required'
else:
opt = 'optional, default=%s' %field.default.__repr__()
text += ' '*indent_offset
text += ' %s -- %s (%s)\n\n' %(name, field.__class__.__name__, opt)
text += wrap(field.title, 78, indent_offset+6)
text += wrap(field.description, 78, indent_offset+6)
return text
def _subDirectiveDocs(subdirs, namespace, name):
"""Appends a list of sub-directives and their full specification."""
if subdirs.has_key((namespace, name)):
text = '\n Subdirectives\n\n'
sub_dirs = []
# Simply walk through all sub-directives here.
for sd_ns, sd_name, sd_schema, sd_info in subdirs[(namespace, name)]:
sub_dirs.append(_directiveDocs(sd_name, sd_schema, sd_info, 4))
return text + '\n\n'.join(sub_dirs)
return ''
def makedocs(target_dir, zcml_file):
"""Generate the documentation tree.
All we need for this is a starting ZCML file and a directory in which to
put the documentation.
"""
context = xmlconfig.file(zcml_file, execute=False)
namespaces, subdirs = makeDocStructures(context)
for namespace, directives in namespaces.items():
ns_dir = os.path.join(target_dir, namespace.split('/')[-1])
# Create a directory for the namespace, if necessary
if not os.path.exists(ns_dir):
os.mkdir(ns_dir)
# Create a file for each directive
for name, (schema, info) in directives.items():
dir_file = os.path.join(ns_dir, name+'.stx')
text = _directiveDocs(name, schema, info)
text += _subDirectiveDocs(subdirs, namespace, name)
open(dir_file, 'w').write(text)
def _makeabs(path):
"""Make an absolute path from the possibly relative path."""
if not path == os.path.abspath(path):
cwd = os.getcwd()
# This is for symlinks.
if os.environ.has_key('PWD'):
cwd = os.environ['PWD']
path = os.path.normpath(os.path.join(cwd, path))
return path
def main(argv=sys.argv):
try:
opts, args = getopt.getopt(
sys.argv[1:],
'h:f:o:',
['help'])
except getopt.error, msg:
usage(1, msg)
zcml_file = None
output_dir = None
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt in ('-o', ):
output_dir = arg
elif opt in ('-f', ):
zcml_file = _makeabs(arg)
if not os.path.exists(zcml_file):
usage(1, 'The specified zcml file does not exist.')
if zcml_file is None or output_dir is None:
usage(0, "Both, the '-f' and '-o' option are required")
# Generate the docs
makedocs(output_dir, zcml_file)
if __name__ == '__main__':
main()
=== Zope3/src/zope/configuration/config.py 1.13 => 1.14 ===
--- Zope3/src/zope/configuration/config.py:1.13 Wed Dec 17 03:06:10 2003
+++ Zope3/src/zope/configuration/config.py Thu Jan 22 18:53:15 2004
@@ -310,11 +310,32 @@
>>> r.register(IConfigurationContext, 'yyy', f)
>>> r.factory(c, ('http://www.zope.com','yyy')) is f
1
+
+ Test the documentation feature:
+
+ >>> r._docRegistry
+ []
+ >>> r.document(('ns', 'dir'), IFullInfo, IConfigurationContext, 'inf', None)
+ >>> r._docRegistry[0][0] == ('ns', 'dir')
+ 1
+ >>> r._docRegistry[0][1] is IFullInfo
+ 1
+ >>> r._docRegistry[0][2] is IConfigurationContext
+ 1
+ >>> r._docRegistry[0][3] == 'inf'
+ 1
+ >>> r._docRegistry[0][4] is None
+ 1
+ >>> r.document('all-dir', None, None, None, None)
+ >>> r._docRegistry[1][0]
+ ('', 'all-dir')
"""
def __init__(self):
self._registry = {}
+ # Stores tuples of form: (namespace, name), schema, usedIn, info, parent
+ self._docRegistry = []
def register(self, interface, name, factory):
r = self._registry.get(name)
@@ -324,6 +345,11 @@
r.register(interface, Interface, factory)
+ def document(self, name, schema, usedIn, info, parent=None):
+ if isinstance(name, (str, unicode)):
+ name = ('', name)
+ self._docRegistry.append((name, schema, usedIn, info, parent))
+
def factory(self, context, name):
r = self._registry.get(name)
if r is None:
@@ -484,7 +510,7 @@
class IStackItem(Interface):
"""Configuration machine stack items
- Stack items are created when a directive if being processed.
+ Stack items are created when a directive is being processed.
A stack item is created for each directive use.
"""
@@ -841,7 +867,7 @@
class GroupingContextDecorator(ConfigurationContext):
"""Helper mix-in class for building grouping directives
- See the discussion (and test) id GroupingStackItem.
+ See the discussion (and test) in GroupingStackItem.
"""
implements(IConfigurationContext, IGroupingContext)
@@ -982,6 +1008,7 @@
return SimpleStackItem(context, handler, info, schema, data)
context.register(usedIn, name, factory)
+ context.document(name, schema, usedIn, context.info)
def defineGroupingDirective(context, name, schema, handler,
namespace='', usedIn=IConfigurationContext):
@@ -1040,6 +1067,7 @@
return GroupingStackItem(newcontext)
context.register(usedIn, name, factory)
+ context.document(name, schema, usedIn, context.info)
class IComplexDirectiveContext(IFullInfo, IConfigurationContext):
@@ -1059,8 +1087,12 @@
return ComplexStackItem(self, context, data, info)
self.register(self.usedIn, (self.namespace, self.name), factory)
+ self.document((self.namespace, self.name), self.schema, self.usedIn,
+ self.info)
def subdirective(context, name, schema):
+ context.document((context.namespace, name), schema, context.usedIn,
+ context.info, context.context)
context.context[name] = schema, context.info
@@ -1354,11 +1386,15 @@
# Define the directive (simple directive) directive by calling it's
# handler directly
+ info = 'Manually registered in zope/configuration/config.py'
+
+ context.info = info
defineSimpleDirective(
context,
namespace=metans, name='directive',
schema=IStandaloneDirectiveInfo,
handler=defineSimpleDirective)
+ context.info = ''
# OK, now that we have that, we can use the machine to define the
# other directives. This isn't the easiest way to proceed, but it lets
@@ -1366,6 +1402,7 @@
# Standalone groupingDirective
context((metans, 'directive'),
+ info,
name='groupingDirective',
namespace=metans,
handler="zope.configuration.config.defineGroupingDirective",
@@ -1374,6 +1411,7 @@
# Now we can use the grouping directive to define the directives directive
context((metans, 'groupingDirective'),
+ info,
name='directives',
namespace=metans,
handler="zope.configuration.config.DirectivesHandler",
@@ -1382,6 +1420,7 @@
# directive and groupingDirective inside directives
context((metans, 'directive'),
+ info,
name='directive',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
@@ -1389,6 +1428,7 @@
schema="zope.configuration.config.IFullInfo"
)
context((metans, 'directive'),
+ info,
name='groupingDirective',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
@@ -1399,12 +1439,14 @@
# Setup complex directive directive, both standalone, and in
# directives directive
context((metans, 'groupingDirective'),
+ info,
name='complexDirective',
namespace=metans,
handler="zope.configuration.config.ComplexDirectiveDefinition",
schema="zope.configuration.config.IStandaloneDirectiveInfo"
)
context((metans, 'groupingDirective'),
+ info,
name='complexDirective',
namespace=metans,
usedIn="zope.configuration.config.IDirectivesContext",
@@ -1414,6 +1456,7 @@
# Finally, setup subdirective directive
context((metans, 'directive'),
+ info,
name='subdirective',
namespace=metans,
usedIn="zope.configuration.config.IComplexDirectiveContext",
More information about the Zope3-Checkins
mailing list