##// END OF EJS Templates
Added tests for IPython.config.application.Application
Brian Granger -
Show More
@@ -1,130 +1,132 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A base class for a configurable application.
3 A base class for a configurable application.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2011 The IPython Development Team
11 # Copyright (C) 2008-2011 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 from copy import deepcopy
21 from copy import deepcopy
22 import logging
22 import logging
23 import sys
23 import sys
24
24
25 from IPython.config.configurable import SingletonConfigurable
25 from IPython.config.configurable import SingletonConfigurable
26 from IPython.utils.traitlets import (
26 from IPython.utils.traitlets import (
27 Unicode, List, Int
27 Unicode, List, Int, Enum
28 )
28 )
29 from IPython.config.loader import (
29 from IPython.config.loader import (
30 KeyValueConfigLoader, PyFileConfigLoader
30 KeyValueConfigLoader, PyFileConfigLoader
31 )
31 )
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Application class
34 # Application class
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37
37
38 class Application(SingletonConfigurable):
38 class Application(SingletonConfigurable):
39
39
40 # The name of the application, will usually match the name of the command
40 # The name of the application, will usually match the name of the command
41 # line application
41 # line application
42 app_name = Unicode(u'application')
42 app_name = Unicode(u'application')
43
43
44 # The description of the application that is printed at the beginning
44 # The description of the application that is printed at the beginning
45 # of the help.
45 # of the help.
46 description = Unicode(u'This is an application.')
46 description = Unicode(u'This is an application.')
47
47
48 # A sequence of Configurable subclasses whose config=True attributes will
48 # A sequence of Configurable subclasses whose config=True attributes will
49 # be exposed at the command line (shortnames and help).
49 # be exposed at the command line (shortnames and help).
50 classes = List([])
50 classes = List([])
51
51
52 # The version string of this application.
52 # The version string of this application.
53 version = Unicode(u'0.0')
53 version = Unicode(u'0.0')
54
54
55 log_level = Int(logging.WARN, config=True, shortname="log_level")
55 # The log level for the application
56 log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN,
57 config=True, shortname="log_level",
58 help="Set the log level (0,10,20,30,40,50).")
56
59
57 def __init__(self, **kwargs):
60 def __init__(self, **kwargs):
58 SingletonConfigurable.__init__(self, **kwargs)
61 SingletonConfigurable.__init__(self, **kwargs)
59 # Add my class to self.classes so my attributes appear in command line
62 # Add my class to self.classes so my attributes appear in command line
60 # options.
63 # options.
61 self.classes.insert(0, self.__class__)
64 self.classes.insert(0, self.__class__)
62 self.init_logging()
65 self.init_logging()
63
66
64 def init_logging(self):
67 def init_logging(self):
65 """Start logging for this application.
68 """Start logging for this application.
66
69
67 The default is to log to stdout using a StreaHandler. The log level
70 The default is to log to stdout using a StreaHandler. The log level
68 starts at loggin.WARN, but this can be adjusted by setting the
71 starts at loggin.WARN, but this can be adjusted by setting the
69 ``log_level`` attribute.
72 ``log_level`` attribute.
70 """
73 """
71 self.log = logging.getLogger(self.__class__.__name__)
74 self.log = logging.getLogger(self.__class__.__name__)
72 self.log.setLevel(self.log_level)
75 self.log.setLevel(self.log_level)
73 self._log_handler = logging.StreamHandler()
76 self._log_handler = logging.StreamHandler()
74 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
77 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
75 self._log_handler.setFormatter(self._log_formatter)
78 self._log_handler.setFormatter(self._log_formatter)
76 self.log.addHandler(self._log_handler)
79 self.log.addHandler(self._log_handler)
77
80
78 def _log_level_changed(self, name, old, new):
81 def _log_level_changed(self, name, old, new):
79 """Adjust the log level when log_level is set."""
82 """Adjust the log level when log_level is set."""
80 self.log.setLevel(new)
83 self.log.setLevel(new)
81
84
82 def print_help(self):
85 def print_help(self):
83 """Print the help for each Configurable class in self.classes."""
86 """Print the help for each Configurable class in self.classes."""
84 for cls in self.classes:
87 for cls in self.classes:
85 cls.class_print_help()
88 cls.class_print_help()
86 print
89 print
87
90
88 def print_description(self):
91 def print_description(self):
89 """Print the application description."""
92 """Print the application description."""
90 print self.description
93 print self.description
91 print
94 print
92
95
93 def print_version(self):
96 def print_version(self):
94 """Print the version string."""
97 """Print the version string."""
95 print self.version
98 print self.version
96
99
97 def update_config(self, config):
100 def update_config(self, config):
98 # Save a copy of the current config.
101 # Save a copy of the current config.
99 newconfig = deepcopy(self.config)
102 newconfig = deepcopy(self.config)
100 # Merge the new config into the current one.
103 # Merge the new config into the current one.
101 newconfig._merge(config)
104 newconfig._merge(config)
102 # Save the combined config as self.config, which triggers the traits
105 # Save the combined config as self.config, which triggers the traits
103 # events.
106 # events.
104 self.config = config
107 self.config = config
105
108
106 def parse_command_line(self, argv=None):
109 def parse_command_line(self, argv=None):
107 """Parse the command line arguments."""
110 """Parse the command line arguments."""
108 if argv is None:
111 argv = sys.argv[1:] if argv is None else argv
109 argv = sys.argv[1:]
110
112
111 if '-h' in argv or '--h' in argv:
113 if '-h' in argv or '--h' in argv:
112 self.print_description()
114 self.print_description()
113 self.print_help()
115 self.print_help()
114 sys.exit(1)
116 sys.exit(1)
115
117
116 if '--version' in argv:
118 if '--version' in argv:
117 self.print_version()
119 self.print_version()
118 sys.exit(1)
120 sys.exit(1)
119
121
120 loader = KeyValueConfigLoader(argv=argv, classes=self.classes)
122 loader = KeyValueConfigLoader(argv=argv, classes=self.classes)
121 config = loader.load_config()
123 config = loader.load_config()
122 self.update_config(config)
124 self.update_config(config)
123
125
124 def load_config_file(self, filename, path=None):
126 def load_config_file(self, filename, path=None):
125 """Load a .py based config file by filename and path."""
127 """Load a .py based config file by filename and path."""
126 # TODO: this raises IOError if filename does not exist.
128 # TODO: this raises IOError if filename does not exist.
127 loader = PyFileConfigLoader(filename, path=path)
129 loader = PyFileConfigLoader(filename, path=path)
128 config = loader.load_config()
130 config = loader.load_config()
129 self.update_config(config)
131 self.update_config(config)
130
132
@@ -1,39 +1,61 b''
1 """A simple example of how to use IPython.config.application.Application.
2
3 This should serve as a simple example that shows how the IPython config
4 system works. The main classes are:
5
6 * IPython.config.configurable.Configurable
7 * IPython.config.configurable.SingletonConfigurable
8 * IPython.config.loader.Config
9 * IPython.config.application.Application
10 """
11
1 import sys
12 import sys
2
13
3 from IPython.config.configurable import Configurable
14 from IPython.config.configurable import Configurable
4 from IPython.config.application import Application
15 from IPython.config.application import Application
5 from IPython.utils.traitlets import (
16 from IPython.utils.traitlets import (
6 Bool, Unicode, Int, Float, List
17 Bool, Unicode, Int, Float, List
7 )
18 )
8
19
9 class Foo(Configurable):
20 class Foo(Configurable):
10
21
11 i = Int(0, config=True, shortname='i', help="The integer i.")
22 i = Int(0, config=True, shortname='i', help="The integer i.")
12 j = Int(1, config=True, shortname='j', help="The integer j.")
23 j = Int(1, config=True, shortname='j', help="The integer j.")
13 name = Unicode(u'Brian', config=True, shortname='name', help="First name.")
24 name = Unicode(u'Brian', config=True, shortname='name', help="First name.")
14
25
15
26
16 class Bar(Configurable):
27 class Bar(Configurable):
17
28
18 enabled = Bool(True, config=True, shortname="bar-enabled", help="Enable bar.")
29 enabled = Bool(True, config=True, shortname="enabled", help="Enable bar.")
19
30
20
31
21 class MyApp(Application):
32 class MyApp(Application):
22
33
23 app_name = Unicode(u'myapp')
34 app_name = Unicode(u'myapp')
24 running = Bool(False, config=True, shortname="running", help="Is the app running?")
35 running = Bool(False, config=True, shortname="running",
36 help="Is the app running?")
25 classes = List([Bar, Foo])
37 classes = List([Bar, Foo])
26 config_file = Unicode(u'', config=True, shortname="config-file", help="Load this config file")
38 config_file = Unicode(u'', config=True, shortname="config_file",
39 help="Load this config file")
40
41 def init_foo(self):
42 self.foo = Foo(config=self.config)
43
44 def init_bar(self):
45 self.bar = Bar(config=self.config)
46
27
47
28
48
29 def main():
49 def main():
30 app = MyApp()
50 app = MyApp()
31 app.parse_command_line()
51 app.parse_command_line()
32 if app.config_file:
52 if app.config_file:
33 app.load_config_file(app.config_file)
53 app.load_config_file(app.config_file)
54 app.init_foo()
55 app.init_bar()
34 print "app.config:"
56 print "app.config:"
35 print app.config
57 print app.config
36
58
37
59
38 if __name__ == "__main__":
60 if __name__ == "__main__":
39 main()
61 main()
General Comments 0
You need to be logged in to leave comments. Login now