[Checkins] SVN: zc.buildout/branches/tlotze-download-api/ merged trunk at rev. 102040

Thomas Lotze tl at gocept.com
Mon Jul 20 12:57:13 EDT 2009


Log message for revision 102041:
  merged trunk at rev. 102040

Changed:
  U   zc.buildout/branches/tlotze-download-api/CHANGES.txt
  U   zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.py
  U   zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.txt

-=-
Modified: zc.buildout/branches/tlotze-download-api/CHANGES.txt
===================================================================
--- zc.buildout/branches/tlotze-download-api/CHANGES.txt	2009-07-20 15:52:36 UTC (rev 102040)
+++ zc.buildout/branches/tlotze-download-api/CHANGES.txt	2009-07-20 16:57:13 UTC (rev 102041)
@@ -4,6 +4,9 @@
 1.3.1 (unreleased)
 ==================
 
+- Added annotate command for annotated sections. Displays sections key-value pairs
+  along with the value origin.
+
 - Added a download API that handles the download cache, offline mode etc and
   is meant to be reused by recipes.
 

Modified: zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.py	2009-07-20 15:52:36 UTC (rev 102040)
+++ zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.py	2009-07-20 16:57:13 UTC (rev 102041)
@@ -28,7 +28,9 @@
 import ConfigParser
 import UserDict
 import glob
+import copy
 
+
 import pkg_resources
 import zc.buildout
 import zc.buildout.download
@@ -65,7 +67,48 @@
     def __str__(self):
         return "The referenced section, %r, was not defined." % self[0]
 
-_buildout_default_options = {
+
+def _annotate_section(section, note):
+    for key in section:
+        section[key] = (section[key], note)
+    return section
+
+def _annotate(data, note):
+    for key in data:
+        data[key] = _annotate_section(data[key], note)
+    return data
+
+def _print_annotate(data):
+    sections = data.keys()
+    sections.sort()
+    print
+    print "Annotated sections"
+    print "="*len("Annotated sections")
+    for section in sections:
+        print
+        print '[%s]' % section
+        keys = data[section].keys()
+        keys.sort()
+        for key in keys:
+            value, files = data[section][key]
+            print "%s=%s" % (key, value)
+            for file in files.split():
+                print "    " + file
+    print
+    print
+
+def _unannotate_section(section):
+    for key in section:
+        value, note = section[key]
+        section[key] = value
+    return section
+
+def _unannotate(data):
+    for key in data:
+        data[key] = _unannotate_section(data[key])
+    return data
+
+_buildout_default_options = _annotate_section({
     'eggs-directory': 'eggs',
     'develop-eggs-directory': 'develop-eggs',
     'bin-directory': 'bin',
@@ -75,8 +118,9 @@
     'executable': sys.executable,
     'log-level': 'INFO',
     'log-format': '',
-    }
+    }, 'DEFAULT_VALUE')
 
+
 class Buildout(UserDict.DictMixin):
 
     def __init__(self, config_file, cloptions,
@@ -101,17 +145,18 @@
                     # Sigh. this model of a buildout nstance
                     # with methods is breaking down :(
                     config_file = None
-                    data['buildout']['directory'] = '.'
+                    data['buildout']['directory'] = ('.', 'COMPUTED_VALUE')
                 else:
                     raise zc.buildout.UserError(
                         "Couldn't open %s" % config_file)
 
             if config_file:
-                data['buildout']['directory'] = os.path.dirname(config_file)
+                data['buildout']['directory'] = (os.path.dirname(config_file),
+                    'COMPUTED_VALUE')
         else:
             base = None
 
-        override = dict((option, value)
+        override = dict((option, (value, 'COMMAND_LINE_VALUE'))
                         for section, option, value in cloptions
                         if section == 'buildout')
 
@@ -133,9 +178,10 @@
             options = data.get(section)
             if options is None:
                 options = data[section] = {}
-            options[option] = value
+            options[option] = value, "COMMAND_LINE_VALUE"
 
-        self._raw = data
+        self._annotated = copy.deepcopy(data)
+        self._raw = _unannotate(data)
         self._data = {}
         self._parts = []
         # provide some defaults before options are parsed
@@ -890,6 +936,9 @@
 
     runsetup = setup # backward compat.
 
+    def annotate(self, args):
+        _print_annotate(self._annotated)
+
     def __getitem__(self, section):
         __doing__ = 'Getting section %s.', section
         try:
@@ -1180,8 +1229,9 @@
     Recursively open other files based on buildout options found.
     """
     _update_section(dl_options, override)
+    _dl_options = _unannotate_section(dl_options.copy())
     download = zc.buildout.download.Download(
-        dl_options, cache=dl_options.get('extends-cache'), fallback=True,
+        _dl_options, cache=_dl_options.get('extends-cache'), fallback=True,
         hash_name=True)
     if _isurl(filename):
         fp = open(download(filename))
@@ -1218,6 +1268,8 @@
             extended_by = options.pop('extended-by', extended_by)
         result[section] = options
 
+    result = _annotate(result, filename)
+
     if root_config_file and 'buildout' in result:
         dl_options = _update_section(dl_options, result['buildout'])
 
@@ -1267,14 +1319,21 @@
 
 def _update_section(s1, s2):
     for k, v in s2.items():
+        v2, note2 = v
         if k.endswith('+'):
             key = k.rstrip(' +')
-            s2[key] = "\n".join(s1.get(key, "").split('\n') + s2[k].split('\n'))
+            v1, note1 = s1.get(key, ("", ""))
+            newnote = ' +'.join((note1, note2)).strip()
+            s2[key] = "\n".join((v1).split('\n') +
+                v2.split('\n')), newnote
             del s2[k]
         elif k.endswith('-'):
             key = k.rstrip(' -')
-            s2[key] = "\n".join([v for v in s1.get(key, "").split('\n')
-                                 if v not in s2[k].split('\n')])
+            v1, note1 = s1.get(key, ("", ""))
+            newnote = ' -'.join((note1, note2)).strip()
+            s2[key] = ("\n".join(
+                [v for v in v1.split('\n')
+                   if v not in v2.split('\n')]), newnote)
             del s2[k]
 
     s1.update(s2)
@@ -1437,6 +1496,13 @@
     The script can be given either as a script path or a path to a
     directory containing a setup.py script.
 
+  annotate
+
+    Display annotated sections. All sections are displayed, sorted
+    alphabetically. For each section, all key-value pairs are displayed,
+    sorted alphabetically, along with the origin of the value (file name or
+    COMPUTED_VALUE, DEFAULT_VALUE, COMMAND_LINE_VALUE).
+
 """
 def _help():
     print _usage
@@ -1456,7 +1522,7 @@
         if args[0][0] == '-':
             op = orig_op = args.pop(0)
             op = op[1:]
-            while op and op[0] in 'vqhWUoOnND':
+            while op and op[0] in 'vqhWUoOnNDA':
                 if op[0] == 'v':
                     verbosity += 10
                 elif op[0] == 'q':
@@ -1525,6 +1591,7 @@
         command = args.pop(0)
         if command not in (
             'install', 'bootstrap', 'runsetup', 'setup', 'init',
+            'annotate',
             ):
             _error('invalid command:', command)
     else:
@@ -1558,7 +1625,7 @@
 
 
     finally:
-            logging.shutdown()
+        logging.shutdown()
 
 if sys.version_info[:2] < (2, 4):
     def reversed(iterable):

Modified: zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.txt	2009-07-20 15:52:36 UTC (rev 102040)
+++ zc.buildout/branches/tlotze-download-api/src/zc/buildout/buildout.txt	2009-07-20 16:57:13 UTC (rev 102041)
@@ -707,6 +707,54 @@
 keep section and option names simple, sticking to alphanumeric
 characters, hyphens, and periods.
 
+Annotated sections
+------------------
+
+When used with the `annotate` command, buildout displays annotated sections. 
+All sections are displayed, sorted alphabetically. For each section,
+all key-value pairs are displayed, sorted alphabetically, along with 
+the origin of the value (file name or COMPUTED_VALUE, DEFAULT_VALUE, 
+COMMAND_LINE_VALUE).
+
+    >>> print system(buildout+ ' annotate'), # doctest: +ELLIPSIS
+    <BLANKLINE>
+    Annotated sections
+    ==================
+    <BLANKLINE>
+    [buildout]
+    bin-directory=bin
+        DEFAULT_VALUE
+    develop=recipes
+        .../_TEST_/sample-buildout/buildout.cfg
+    develop-eggs-directory=develop-eggs
+        DEFAULT_VALUE
+    directory=.../_TEST_/sample-buildout
+        COMPUTED_VALUE
+    eggs-directory=eggs
+        DEFAULT_VALUE
+    executable=...
+        DEFAULT_VALUE
+    installed=.installed.cfg
+        DEFAULT_VALUE
+    log-format=
+        DEFAULT_VALUE
+    log-level=INFO
+        DEFAULT_VALUE
+    parts=data-dir
+        .../_TEST_/sample-buildout/buildout.cfg
+    parts-directory=parts
+        DEFAULT_VALUE
+    python=buildout
+        DEFAULT_VALUE
+    <BLANKLINE>
+    [data-dir]
+    path=foo bins
+        .../_TEST_/sample-buildout/buildout.cfg
+    recipe=recipes:mkdir
+        .../_TEST_/sample-buildout/buildout.cfg
+    <BLANKLINE>
+    <BLANKLINE>
+
 Variable substitutions
 ----------------------
 
@@ -1025,6 +1073,46 @@
     ['a1 a2/na3 a4/na5', 'b1 b2 b3 b4', 'c1 c2/nc3 c4 c5', 'h1 h2']
     Develop: '/sample-buildout/demo'
 
+Annotated sections output shows which files are responsible for which
+operations.
+
+    >>> print system(os.path.join('bin', 'buildout') + ' annotate'), # doctest: +ELLIPSIS
+    <BLANKLINE>
+    Annotated sections
+    ==================
+    ...
+    <BLANKLINE>
+    [part1]
+    option=a1 a2
+    a3 a4
+    a5
+        .../_TEST_/sample-buildout/base.cfg
+        +.../_TEST_/sample-buildout/extension1.cfg
+        +.../_TEST_/sample-buildout/extension2.cfg
+    recipe=
+        .../_TEST_/sample-buildout/base.cfg
+    <BLANKLINE>
+    [part2]
+    option=b1 b2 b3 b4
+        .../_TEST_/sample-buildout/base.cfg
+        -.../_TEST_/sample-buildout/extension1.cfg
+        -.../_TEST_/sample-buildout/extension2.cfg
+    recipe=
+        .../_TEST_/sample-buildout/base.cfg
+    <BLANKLINE>
+    [part3]
+    option=c1 c2
+    c3 c4 c5
+        .../_TEST_/sample-buildout/base.cfg
+        +.../_TEST_/sample-buildout/extension1.cfg
+    recipe=
+        .../_TEST_/sample-buildout/base.cfg
+    <BLANKLINE>
+    [part4]
+    option=h1 h2
+        .../_TEST_/sample-buildout/extension1.cfg
+    ...
+
 Cleanup.
 
     >>> os.remove(os.path.join(sample_buildout, 'base.cfg'))



More information about the Checkins mailing list