From e957fe673d03881587048662fd33e66477b18c7e 2011-05-17 19:37:16
From: MinRK <benjaminrk@gmail.com>
Date: 2011-05-17 19:37:16
Subject: [PATCH] rename macros/shortnames to flags/aliases

also remove macro_help in favor of alias values being tuples.
---

diff --git a/IPython/config/application.py b/IPython/config/application.py
index 17de568..b2122cd 100644
--- a/IPython/config/application.py
+++ b/IPython/config/application.py
@@ -24,7 +24,7 @@ import sys
 
 from IPython.config.configurable import SingletonConfigurable
 from IPython.config.loader import (
-    KeyValueConfigLoader, PyFileConfigLoader
+    KeyValueConfigLoader, PyFileConfigLoader, Config
 )
 
 from IPython.utils.traitlets import (
@@ -36,14 +36,14 @@ from IPython.utils.text import indent
 # Descriptions for
 #-----------------------------------------------------------------------------
 
-macro_description = """
+flag_description = """
 Flags are command-line arguments passed as '--<flag>'.
 These take no parameters, unlike regular key-value arguments.
 They are typically used for setting boolean flags, or enabling
 modes that involve setting multiple options together.
 """.strip() # trim newlines of front and back
 
-shortname_description = """
+alias_description = """
 These are commonly set parameters, given abbreviated aliases for convenience.
 They are set in the same `name=value` way as class parameters, where
 <name> is replaced by the real parameter for which it is an alias.
@@ -72,13 +72,13 @@ class Application(SingletonConfigurable):
     # of the help.
     description = Unicode(u'This is an application.')
     # default section descriptions
-    macro_description = Unicode(macro_description)
-    shortname_description = Unicode(shortname_description)
+    flag_description = Unicode(flag_description)
+    alias_description = Unicode(alias_description)
     keyvalue_description = Unicode(keyvalue_description)
     
 
     # A sequence of Configurable subclasses whose config=True attributes will
-    # be exposed at the command line (shortnames and help).
+    # be exposed at the command line.
     classes = List([])
 
     # The version string of this application.
@@ -89,14 +89,14 @@ class Application(SingletonConfigurable):
                      config=True,
                      help="Set the log level (0,10,20,30,40,50).")
     
-    # the shortname map for configurables
-    shortnames = Dict(dict(log_level='Application.log_level'))
+    # the alias map for configurables
+    aliases = Dict(dict(log_level='Application.log_level'))
     
-    # macros for loading Configurables or store_const style flags
-    # macros are loaded from this dict by '--key' flags
-    macros = Dict()
-    # macro_help dict keys must match macros
-    macro_help = Dict()
+    # flags for loading Configurables or store_const style flags
+    # flags are loaded from this dict by '--key' flags
+    # this must be a dict of two-tuples, the first element being the Config/dict
+    # and the second being the help string for the flag
+    flags = Dict()
     
 
     def __init__(self, **kwargs):
@@ -105,12 +105,11 @@ class Application(SingletonConfigurable):
         # options.
         self.classes.insert(0, self.__class__)
         
-        # check that macro_help has the right keys
-        # there is probably a better way to do this that doesn't use 2 dicts
-        keys = set(self.macros.keys())
-        badkeys = keys.difference_update(set(self.macro_help.keys()))
-        if badkeys:
-            raise KeyError("macro %r has no help in `macro_help`!"%badkeys.pop())
+        # ensure self.flags dict is valid
+        for key,value in self.flags.iteritems():
+            assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
+            assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
+            assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
         self.init_logging()
     
     def init_logging(self):
@@ -131,50 +130,50 @@ class Application(SingletonConfigurable):
         """Adjust the log level when log_level is set."""
         self.log.setLevel(new)
     
-    def print_shortname_help(self):
-        """print the shortname part of the help"""
-        if not self.shortnames:
+    def print_alias_help(self):
+        """print the alias part of the help"""
+        if not self.aliases:
             return
             
         print "Aliases"
         print "-------"
-        print self.shortname_description
+        print self.alias_description
         print
         
         classdict = {}
         for c in self.classes:
             classdict[c.__name__] = c
         
-        for shortname, longname in self.shortnames.iteritems():
+        for alias, longname in self.aliases.iteritems():
             classname, traitname = longname.split('.',1)
             cls = classdict[classname]
             
             trait = cls.class_traits(config=True)[traitname]
             help = trait.get_metadata('help')
-            print shortname, "(%s)"%longname, ':', trait.__class__.__name__
+            print alias, "(%s)"%longname, ':', trait.__class__.__name__
             if help:
                 print indent(help)
         print
     
-    def print_macro_help(self):
-        """print the the macro part of the help"""
-        if not self.macros:
+    def print_flag_help(self):
+        """print the flag part of the help"""
+        if not self.flags:
             return
         
         print "Flags"
         print "-----"
-        print self.macro_description
+        print self.flag_description
         print
         
-        for m, cfg in self.macros.iteritems():
+        for m, (cfg,help) in self.flags.iteritems():
             print '--'+m
-            print indent(self.macro_help[m])
+            print indent(help)
         print
     
     def print_help(self):
         """Print the help for each Configurable class in self.classes."""
-        self.print_macro_help()
-        self.print_shortname_help()
+        self.print_flag_help()
+        self.print_alias_help()
         if self.classes:
             print "Class parameters"
             print "----------------"
@@ -216,9 +215,9 @@ class Application(SingletonConfigurable):
         if '--version' in argv:
             self.print_version()
             sys.exit(1)
-
-        loader = KeyValueConfigLoader(argv=argv, shortnames=self.shortnames,
-                                        macros=self.macros)
+        
+        loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
+                                        flags=self.flags)
         config = loader.load_config()
         self.update_config(config)
 
diff --git a/IPython/config/loader.py b/IPython/config/loader.py
index 1415338..c9bb642 100644
--- a/IPython/config/loader.py
+++ b/IPython/config/loader.py
@@ -305,7 +305,7 @@ class CommandLineConfigLoader(ConfigLoader):
     """
 
 kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.+')
-macro_pattern = re.compile(r'\-\-\w+(\-\w)*')
+flag_pattern = re.compile(r'\-\-\w+(\-\w)*')
 
 class KeyValueConfigLoader(CommandLineConfigLoader):
     """A config loader that loads key value pairs from the command line.
@@ -315,7 +315,7 @@ class KeyValueConfigLoader(CommandLineConfigLoader):
         ipython Global.profile="foo" InteractiveShell.autocall=False
     """
 
-    def __init__(self, argv=None, shortnames=None, macros=None):
+    def __init__(self, argv=None, aliases=None, flags=None):
         """Create a key value pair config loader.
 
         Parameters
@@ -324,14 +324,14 @@ class KeyValueConfigLoader(CommandLineConfigLoader):
             A list that has the form of sys.argv[1:] which has unicode
             elements of the form u"key=value". If this is None (default),
             then sys.argv[1:] will be used.
-        shortnames : dict
+        aliases : dict
             A dict of aliases for configurable traits.
             Keys are the short aliases, Values are the resolved trait.
-            Of the form: `{'shortname' : 'Configurable.trait'}`
-        macros : dict
-            A dict of macros, keyed by str name. Vaues can be Config objects,
-            dicts, or "key=value" strings.  If Config or dict, when the macro
-            is triggered, The macro is loaded as `self.config.update(m)`.
+            Of the form: `{'alias' : 'Configurable.trait'}`
+        flags : dict
+            A dict of flags, keyed by str name. Vaues can be Config objects,
+            dicts, or "key=value" strings.  If Config or dict, when the flag
+            is triggered, The flag is loaded as `self.config.update(m)`.
 
         Returns
         -------
@@ -349,10 +349,10 @@ class KeyValueConfigLoader(CommandLineConfigLoader):
         if argv is None:
             argv = sys.argv[1:]
         self.argv = argv
-        self.shortnames = shortnames or {}
-        self.macros = macros or {}
+        self.aliases = aliases or {}
+        self.flags = flags or {}
 
-    def load_config(self, argv=None, shortnames=None, macros=None):
+    def load_config(self, argv=None, aliases=None, flags=None):
         """Parse the configuration and generate the Config object.
 
         Parameters
@@ -361,31 +361,31 @@ class KeyValueConfigLoader(CommandLineConfigLoader):
             A list that has the form of sys.argv[1:] which has unicode
             elements of the form u"key=value". If this is None (default),
             then self.argv will be used.
-        shortnames : dict
+        aliases : dict
             A dict of aliases for configurable traits.
             Keys are the short aliases, Values are the resolved trait.
-            Of the form: `{'shortname' : 'Configurable.trait'}`
-        macros : dict
-            A dict of macros, keyed by str name. Vaues can be Config objects,
-            dicts, or "key=value" strings.  If Config or dict, when the macro
-            is triggered, The macro is loaded as `self.config.update(m)`.
+            Of the form: `{'alias' : 'Configurable.trait'}`
+        flags : dict
+            A dict of flags, keyed by str name. Values can be Config objects
+            or dicts.  When the flag is triggered, The config is loaded as 
+            `self.config.update(cfg)`.
         """
         from IPython.config.configurable import Configurable
 
         self.clear()
         if argv is None:
             argv = self.argv
-        if shortnames is None:
-            shortnames = self.shortnames
-        if macros is None:
-            macros = self.macros
+        if aliases is None:
+            aliases = self.aliases
+        if flags is None:
+            flags = self.flags
 
         for item in argv:
             if kv_pattern.match(item):
                 lhs,rhs = item.split('=',1)
-                # Substitute longnames for shortnames.
-                if lhs in shortnames:
-                    lhs = shortnames[lhs]
+                # Substitute longnames for aliases.
+                if lhs in aliases:
+                    lhs = aliases[lhs]
                 exec_str = 'self.config.' + lhs + '=' + rhs
                 try:
                     # Try to see if regular Python syntax will work. This
@@ -398,18 +398,17 @@ class KeyValueConfigLoader(CommandLineConfigLoader):
                     # it succeeds. If it still fails, we let it raise.
                     exec_str = 'self.config.' + lhs + '="' + rhs + '"'
                     exec exec_str in locals(), globals()
-            elif macro_pattern.match(item):
+            elif flag_pattern.match(item):
                 # trim leading '--'
                 m = item[2:]
-                macro = macros.get(m, None)
-                if macro is None:
-                    raise ValueError("Unrecognized argument: %r"%item)
-                macro = macros[m]
-                if isinstance(macro, (dict, Configurable)):
+                cfg,_ = flags.get(m, (None,None))
+                if cfg is None:
+                    raise ValueError("Unrecognized flag: %r"%item)
+                elif isinstance(cfg, (dict, Config)):
                     # update self.config with Config:
-                    self.config.update(macros[m])
+                    self.config.update(cfg)
                 else:
-                    raise ValueError("Invalid macro: %r"%macro)
+                    raise ValueError("Invalid flag: %r"%flag)
             else:
                 raise ValueError("Invalid argument: %r"%item)
         return self.config
diff --git a/IPython/config/tests/test_application.py b/IPython/config/tests/test_application.py
index 458cf66..d98166a 100644
--- a/IPython/config/tests/test_application.py
+++ b/IPython/config/tests/test_application.py
@@ -26,7 +26,7 @@ from IPython.config.application import (
 )
 
 from IPython.utils.traitlets import (
-    Bool, Unicode, Int, Float, List
+    Bool, Unicode, Int, Float, List, Dict
 )
 
 #-----------------------------------------------------------------------------
@@ -48,21 +48,18 @@ class Bar(Configurable):
 class MyApp(Application):
 
     app_name = Unicode(u'myapp')
-    running = Bool(False, config=True, shortname="running",
+    running = Bool(False, config=True,
                    help="Is the app running?")
     classes = List([Bar, Foo])
-    config_file = Unicode(u'', config=True, shortname="config_file",
+    config_file = Unicode(u'', config=True,
                    help="Load this config file")
 
-    shortnames = dict(i='Foo.i',j='Foo.j',name='Foo.name',
-                    enabled='Bar.enabled', log_level='MyApp.log_level')
+    aliases = Dict(dict(i='Foo.i',j='Foo.j',name='Foo.name',
+                    enabled='Bar.enabled', log_level='MyApp.log_level'))
+    
+    flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"),
+                  disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False")))
     
-    macros = dict(enable={'Bar': {'enabled' : True}}, disable={'Bar': {'enabled' : False}})
-
-    macro_help = dict(
-            enable="""Enable bar""",
-            disable="""Disable bar"""
-    )
     def init_foo(self):
         self.foo = Foo(config=self.config)
 
@@ -97,7 +94,7 @@ class TestApplication(TestCase):
         self.assertEquals(app.foo.j, 10)
         self.assertEquals(app.bar.enabled, False)
 
-    def test_macro(self):
+    def test_alias(self):
         app = MyApp()
         app.parse_command_line(["--disable"])
         app.init_bar()
diff --git a/docs/examples/core/appconfig.py b/docs/examples/core/appconfig.py
index b09ed61..d0c1d10 100644
--- a/docs/examples/core/appconfig.py
+++ b/docs/examples/core/appconfig.py
@@ -35,7 +35,7 @@ import sys
 from IPython.config.configurable import Configurable
 from IPython.config.application import Application
 from IPython.utils.traitlets import (
-    Bool, Unicode, Int, Float, List
+    Bool, Unicode, Int, Float, List, Dict
 )
 
 
@@ -63,15 +63,14 @@ class MyApp(Application):
     config_file = Unicode(u'', config=True,
                    help="Load this config file")
     
-    shortnames = dict(i='Foo.i',j='Foo.j',name='Foo.name', running='MyApp.running',
-                        enabled='Bar.enabled')
+    aliases = Dict(dict(i='Foo.i',j='Foo.j',name='Foo.name', running='MyApp.running',
+                        enabled='Bar.enabled', log_level='MyApp.log_level'))
+    
+    flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Enable Bar"),
+                  disable=({'Bar': {'enabled' : False}}, "Disable Bar"),
+                  debug=({'MyApp':{'log_level':10}}, "Set loglevel to DEBUG")
+            ))
     
-    macros = dict(enable={'Bar': {'enabled' : True}}, disable={'Bar': {'enabled' : False}})
-    macro_help = dict(
-            enable="""Set Bar.enabled to True""",
-            disable="""Set Bar.enabled to False"""
-    )
-
     def init_foo(self):
         # Pass config to other classes for them to inherit the config.
         self.foo = Foo(config=self.config)
@@ -91,7 +90,6 @@ def main():
     app.init_bar()
     print "app.config:"
     print app.config
-    print app.bar.enabled
 
 
 if __name__ == "__main__":