##// END OF EJS Templates
Updating the docs.
Brian Granger -
Show More
@@ -0,0 +1,5 b''
1 .. _extensions_overview:
2
3 ==================
4 IPython extensions
5 ================== No newline at end of file
@@ -1,331 +1,329 b''
1 .. _config_overview:
1 .. _config_overview:
2
2
3 ============================================
3 ============================================
4 Overview of the IPython configuration system
4 Overview of the IPython configuration system
5 ============================================
5 ============================================
6
6
7 This section describes the IPython configuration system. Starting with version
7 This section describes the IPython configuration system. Starting with version
8 0.11, IPython has a completely new configuration system that is quite
8 0.11, IPython has a completely new configuration system that is quite
9 different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py`
9 different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py`
10 approaches. The new configuration system was designed from scratch to address
10 approaches. The new configuration system was designed from scratch to address
11 the particular configuration needs of IPython. While there are many
11 the particular configuration needs of IPython. While there are many
12 other excellent configuration systems out there, we found that none of them
12 other excellent configuration systems out there, we found that none of them
13 met our requirements.
13 met our requirements.
14
14
15 .. warning::
15 .. warning::
16
16
17 If you are upgrading to version 0.11 of IPython, you will need to migrate
17 If you are upgrading to version 0.11 of IPython, you will need to migrate
18 your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files
18 your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files
19 to the new system. Read on for information on how to do this.
19 to the new system. Read on for information on how to do this.
20
20
21 The discussion that follows is focused on teaching user's how to configure
21 The discussion that follows is focused on teaching user's how to configure
22 IPython to their liking. Developer's who want to know more about how they
22 IPython to their liking. Developer's who want to know more about how they
23 can enable their objects to take advantage of the configuration system
23 can enable their objects to take advantage of the configuration system
24 should consult our :ref:`developer guide <developer_guide>`
24 should consult our :ref:`developer guide <developer_guide>`
25
25
26 The main concepts
26 The main concepts
27 =================
27 =================
28
28
29 There are a number of abstractions that the IPython configuration system uses.
29 There are a number of abstractions that the IPython configuration system uses.
30 Each of these abstractions is represented by a Python class.
30 Each of these abstractions is represented by a Python class.
31
31
32 Configuration object: :class:`~IPython.config.loader.Config`
32 Configuration object: :class:`~IPython.config.loader.Config`
33 A configuration object is a simple dictionary-like class that holds
33 A configuration object is a simple dictionary-like class that holds
34 configuration attributes and sub-configuration objects. These classes
34 configuration attributes and sub-configuration objects. These classes
35 support dotted attribute style access (``Foo.bar``) in addition to the
35 support dotted attribute style access (``Foo.bar``) in addition to the
36 regular dictionary style access (``Foo['bar']``). Configuration objects
36 regular dictionary style access (``Foo['bar']``). Configuration objects
37 are smart. They know how to merge themselves with other configuration
37 are smart. They know how to merge themselves with other configuration
38 objects and they automatically create sub-configuration objects.
38 objects and they automatically create sub-configuration objects.
39
39
40 Application: :class:`~IPython.core.application.Application`
40 Application: :class:`~IPython.core.application.Application`
41 An application is a process that does a specific job. The most obvious
41 An application is a process that does a specific job. The most obvious
42 application is the :command:`ipython` command line program. Each
42 application is the :command:`ipython` command line program. Each
43 application reads a *single* configuration file and command line options
43 application reads a *single* configuration file and command line options
44 and then produces a master configuration object for the application. This
44 and then produces a master configuration object for the application. This
45 configuration object is then passed to the components that the application
45 configuration object is then passed to the configurable objects that the
46 creates. Components implement the actual logic of the application and know
46 application creates. These configurable objects implement the actual logic
47 how to configure themselves given the configuration object.
47 of the application and know how to configure themselves given the
48
48 configuration object.
49 Component: :class:`~IPython.core.component.Component`
49
50 A component is a regular Python class that serves as a base class for all
50 Component: :class:`~IPython.config.configurable.Configurable`
51 main classes in an application. The
51 A configurable is a regular Python class that serves as a base class for
52 :class:`~IPython.core.component.Component` base class is lightweight and
52 all main classes in an application. The
53 only does two main things.
53 :class:`~IPython.config.configurable.Configurable` base class is
54 lightweight and only does one things.
55
56 This :class:`~IPython.config.configurable.Configurable` is a subclass
57 of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure
58 itself. Class level traits with the metadata ``config=True`` become
59 values that can be configured from the command line and configuration
60 files.
54
61
55 First, it keeps track of all instances of itself and provides an
62 Developers create :class:`~IPython.config.configurable.Configurable`
56 interfaces for querying those instances. This enables components to get
63 subclasses that implement all of the logic in the application. Each of
57 references to other components, even though they are not "nearby" in the
64 these subclasses has its own configuration information that controls how
58 runtime object graph.
59
60 Second, it declares what class attributes are configurable and specifies
61 the default types and values of those attributes. This information is used
62 to automatically configure instances given the applications configuration
63 object.
64
65 Developers create :class:`~IPython.core.component.Component` subclasses
66 that implement all of the logic in the application. Each of these
67 subclasses has its own configuration information that controls how
68 instances are created.
65 instances are created.
69
66
70 Having described these main concepts, we can now state the main idea in our
67 Having described these main concepts, we can now state the main idea in our
71 configuration system: *"configuration" allows the default values of class
68 configuration system: *"configuration" allows the default values of class
72 attributes to be controlled on a class by class basis*. Thus all instances of
69 attributes to be controlled on a class by class basis*. Thus all instances of
73 a given class are configured in the same way. Furthermore, if two instances
70 a given class are configured in the same way. Furthermore, if two instances
74 need to be configured differently, they need to be instances of two different
71 need to be configured differently, they need to be instances of two different
75 classes. While this model may seem a bit restrictive, we have found that it
72 classes. While this model may seem a bit restrictive, we have found that it
76 expresses most things that need to be configured extremely well.
73 expresses most things that need to be configured extremely well. However, it
74 is possible to create two instances of the same class that have different
75 trait values. This is done by overriding the configuration.
77
76
78 Now, we show what our configuration objects and files look like.
77 Now, we show what our configuration objects and files look like.
79
78
80 Configuration objects and files
79 Configuration objects and files
81 ===============================
80 ===============================
82
81
83 A configuration file is simply a pure Python file that sets the attributes
82 A configuration file is simply a pure Python file that sets the attributes
84 of a global, pre-created configuration object. This configuration object is a
83 of a global, pre-created configuration object. This configuration object is a
85 :class:`~IPython.config.loader.Config` instance. While in a configuration
84 :class:`~IPython.config.loader.Config` instance. While in a configuration
86 file, to get a reference to this object, simply call the :func:`get_config`
85 file, to get a reference to this object, simply call the :func:`get_config`
87 function. We inject this function into the global namespace that the
86 function. We inject this function into the global namespace that the
88 configuration file is executed in.
87 configuration file is executed in.
89
88
90 Here is an example of a super simple configuration file that does nothing::
89 Here is an example of a super simple configuration file that does nothing::
91
90
92 c = get_config()
91 c = get_config()
93
92
94 Once you get a reference to the configuration object, you simply set
93 Once you get a reference to the configuration object, you simply set
95 attributes on it. All you have to know is:
94 attributes on it. All you have to know is:
96
95
97 * The name of each attribute.
96 * The name of each attribute.
98 * The type of each attribute.
97 * The type of each attribute.
99
98
100 The answers to these two questions are provided by the various
99 The answers to these two questions are provided by the various
101 :class:`~IPython.core.component.Component` subclasses that an application
100 :class:`~IPython.config.configurable.Configurable` subclasses that an
102 uses. Let's look at how this would work for a simple component subclass::
101 application uses. Let's look at how this would work for a simple component
102 subclass::
103
103
104 # Sample component that can be configured.
104 # Sample component that can be configured.
105 from IPython.core.component import Component
105 from IPython.config.configurable import Configurable
106 from IPython.utils.traitlets import Int, Float, Str, Bool
106 from IPython.utils.traitlets import Int, Float, Str, Bool
107
107
108 class MyComponent(Component):
108 class MyClass(Configurable):
109 name = Str('defaultname', config=True)
109 name = Str('defaultname', config=True)
110 ranking = Int(0, config=True)
110 ranking = Int(0, config=True)
111 value = Float(99.0)
111 value = Float(99.0)
112 # The rest of the class implementation would go here..
112 # The rest of the class implementation would go here..
113
113
114 In this example, we see that :class:`MyComponent` has three attributes, two
114 In this example, we see that :class:`MyClass` has three attributes, two
115 of whom (``name``, ``ranking``) can be configured. All of the attributes
115 of whom (``name``, ``ranking``) can be configured. All of the attributes
116 are given types and default values. If a :class:`MyComponent` is instantiated,
116 are given types and default values. If a :class:`MyClass` is instantiated,
117 but not configured, these default values will be used. But let's see how
117 but not configured, these default values will be used. But let's see how
118 to configure this class in a configuration file::
118 to configure this class in a configuration file::
119
119
120 # Sample config file
120 # Sample config file
121 c = get_config()
121 c = get_config()
122
122
123 c.MyComponent.name = 'coolname'
123 c.MyClass.name = 'coolname'
124 c.MyComponent.ranking = 10
124 c.MyClass.ranking = 10
125
125
126 After this configuration file is loaded, the values set in it will override
126 After this configuration file is loaded, the values set in it will override
127 the class defaults anytime a :class:`MyComponent` is created. Furthermore,
127 the class defaults anytime a :class:`MyClass` is created. Furthermore,
128 these attributes will be type checked and validated anytime they are set.
128 these attributes will be type checked and validated anytime they are set.
129 This type checking is handled by the :mod:`IPython.utils.traitlets` module,
129 This type checking is handled by the :mod:`IPython.utils.traitlets` module,
130 which provides the :class:`Str`, :class:`Int` and :class:`Float` types. In
130 which provides the :class:`Str`, :class:`Int` and :class:`Float` types. In
131 addition to these traitlets, the :mod:`IPython.utils.traitlets` provides
131 addition to these traitlets, the :mod:`IPython.utils.traitlets` provides
132 traitlets for a number of other types.
132 traitlets for a number of other types.
133
133
134 .. note::
134 .. note::
135
135
136 Underneath the hood, the :class:`Component` base class is a subclass of
136 Underneath the hood, the :class:`Configurable` base class is a subclass of
137 :class:`IPython.utils.traitlets.HasTraits`. The
137 :class:`IPython.utils.traitlets.HasTraits`. The
138 :mod:`IPython.utils.traitlets` module is a lightweight version of
138 :mod:`IPython.utils.traitlets` module is a lightweight version of
139 :mod:`enthought.traits`. Our implementation is a pure Python subset
139 :mod:`enthought.traits`. Our implementation is a pure Python subset
140 (mostly API compatible) of :mod:`enthought.traits` that does not have any
140 (mostly API compatible) of :mod:`enthought.traits` that does not have any
141 of the automatic GUI generation capabilities. Our plan is to achieve 100%
141 of the automatic GUI generation capabilities. Our plan is to achieve 100%
142 API compatibility to enable the actual :mod:`enthought.traits` to
142 API compatibility to enable the actual :mod:`enthought.traits` to
143 eventually be used instead. Currently, we cannot use
143 eventually be used instead. Currently, we cannot use
144 :mod:`enthought.traits` as we are committed to the core of IPython being
144 :mod:`enthought.traits` as we are committed to the core of IPython being
145 pure Python.
145 pure Python.
146
146
147 It should be very clear at this point what the naming convention is for
147 It should be very clear at this point what the naming convention is for
148 configuration attributes::
148 configuration attributes::
149
149
150 c.ClassName.attribute_name = attribute_value
150 c.ClassName.attribute_name = attribute_value
151
151
152 Here, ``ClassName`` is the name of the class whose configuration attribute you
152 Here, ``ClassName`` is the name of the class whose configuration attribute you
153 want to set, ``attribute_name`` is the name of the attribute you want to set
153 want to set, ``attribute_name`` is the name of the attribute you want to set
154 and ``attribute_value`` the the value you want it to have. The ``ClassName``
154 and ``attribute_value`` the the value you want it to have. The ``ClassName``
155 attribute of ``c`` is not the actual class, but instead is another
155 attribute of ``c`` is not the actual class, but instead is another
156 :class:`~IPython.config.loader.Config` instance.
156 :class:`~IPython.config.loader.Config` instance.
157
157
158 .. note::
158 .. note::
159
159
160 The careful reader may wonder how the ``ClassName`` (``MyComponent`` in
160 The careful reader may wonder how the ``ClassName`` (``MyClass`` in
161 the above example) attribute of the configuration object ``c`` gets
161 the above example) attribute of the configuration object ``c`` gets
162 created. These attributes are created on the fly by the
162 created. These attributes are created on the fly by the
163 :class:`~IPython.config.loader.Config` instance, using a simple naming
163 :class:`~IPython.config.loader.Config` instance, using a simple naming
164 convention. Any attribute of a :class:`~IPython.config.loader.Config`
164 convention. Any attribute of a :class:`~IPython.config.loader.Config`
165 instance whose name begins with an uppercase character is assumed to be a
165 instance whose name begins with an uppercase character is assumed to be a
166 sub-configuration and a new empty :class:`~IPython.config.loader.Config`
166 sub-configuration and a new empty :class:`~IPython.config.loader.Config`
167 instance is dynamically created for that attribute. This allows deeply
167 instance is dynamically created for that attribute. This allows deeply
168 hierarchical information created easily (``c.Foo.Bar.value``) on the
168 hierarchical information created easily (``c.Foo.Bar.value``) on the fly.
169 fly.
170
169
171 Configuration files inheritance
170 Configuration files inheritance
172 ===============================
171 ===============================
173
172
174 Let's say you want to have different configuration files for various purposes.
173 Let's say you want to have different configuration files for various purposes.
175 Our configuration system makes it easy for one configuration file to inherit
174 Our configuration system makes it easy for one configuration file to inherit
176 the information in another configuration file. The :func:`load_subconfig`
175 the information in another configuration file. The :func:`load_subconfig`
177 command can be used in a configuration file for this purpose. Here is a simple
176 command can be used in a configuration file for this purpose. Here is a simple
178 example that loads all of the values from the file :file:`base_config.py`::
177 example that loads all of the values from the file :file:`base_config.py`::
179
178
180 # base_config.py
179 # base_config.py
181 c = get_config()
180 c = get_config()
182 c.MyComponent.name = 'coolname'
181 c.MyClass.name = 'coolname'
183 c.MyComponent.ranking = 100
182 c.MyClass.ranking = 100
184
183
185 into the configuration file :file:`main_config.py`::
184 into the configuration file :file:`main_config.py`::
186
185
187 # main_config.py
186 # main_config.py
188 c = get_config()
187 c = get_config()
189
188
190 # Load everything from base_config.py
189 # Load everything from base_config.py
191 load_subconfig('base_config.py')
190 load_subconfig('base_config.py')
192
191
193 # Now override one of the values
192 # Now override one of the values
194 c.MyComponent.name = 'bettername'
193 c.MyClass.name = 'bettername'
195
194
196 In a situation like this the :func:`load_subconfig` makes sure that the
195 In a situation like this the :func:`load_subconfig` makes sure that the
197 search path for sub-configuration files is inherited from that of the parent.
196 search path for sub-configuration files is inherited from that of the parent.
198 Thus, you can typically put the two in the same directory and everything will
197 Thus, you can typically put the two in the same directory and everything will
199 just work.
198 just work.
200
199
201 Class based configuration inheritance
200 Class based configuration inheritance
202 =====================================
201 =====================================
203
202
204 There is another aspect of configuration where inheritance comes into play.
203 There is another aspect of configuration where inheritance comes into play.
205 Sometimes, your classes will have an inheritance hierarchy that you want
204 Sometimes, your classes will have an inheritance hierarchy that you want
206 to be reflected in the configuration system. Here is a simple example::
205 to be reflected in the configuration system. Here is a simple example::
207
206
208 from IPython.core.component import Component
207 from IPython.config.configurable import Configurable
209 from IPython.utils.traitlets import Int, Float, Str, Bool
208 from IPython.utils.traitlets import Int, Float, Str, Bool
210
209
211 class Foo(Component):
210 class Foo(Configurable):
212 name = Str('fooname', config=True)
211 name = Str('fooname', config=True)
213 value = Float(100.0, config=True)
212 value = Float(100.0, config=True)
214
213
215 class Bar(Foo):
214 class Bar(Foo):
216 name = Str('barname', config=True)
215 name = Str('barname', config=True)
217 othervalue = Int(0, config=True)
216 othervalue = Int(0, config=True)
218
217
219 Now, we can create a configuration file to configure instances of :class:`Foo`
218 Now, we can create a configuration file to configure instances of :class:`Foo`
220 and :class:`Bar`::
219 and :class:`Bar`::
221
220
222 # config file
221 # config file
223 c = get_config()
222 c = get_config()
224
223
225 c.Foo.name = 'bestname'
224 c.Foo.name = 'bestname'
226 c.Bar.othervalue = 10
225 c.Bar.othervalue = 10
227
226
228 This class hierarchy and configuration file accomplishes the following:
227 This class hierarchy and configuration file accomplishes the following:
229
228
230 * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be
229 * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be
231 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also
230 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also
232 picks up the configuration information for :class:`Foo`.
231 picks up the configuration information for :class:`Foo`.
233 * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be
232 * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be
234 ``100.0``, which is the value specified as the class default.
233 ``100.0``, which is the value specified as the class default.
235 * The default value for :attr:`Bar.othervalue` will be 10 as set in the
234 * The default value for :attr:`Bar.othervalue` will be 10 as set in the
236 configuration file. Because :class:`Foo` is the parent of :class:`Bar`
235 configuration file. Because :class:`Foo` is the parent of :class:`Bar`
237 it doesn't know anything about the :attr:`othervalue` attribute.
236 it doesn't know anything about the :attr:`othervalue` attribute.
238
237
239 Configuration file location
238 Configuration file location
240 ===========================
239 ===========================
241
240
242 So where should you put your configuration files? By default, all IPython
241 So where should you put your configuration files? By default, all IPython
243 applications look in the so called "IPython directory". The location of
242 applications look in the so called "IPython directory". The location of
244 this directory is determined by the following algorithm:
243 this directory is determined by the following algorithm:
245
244
246 * If the ``--ipython-dir`` command line flag is given, its value is used.
245 * If the ``--ipython-dir`` command line flag is given, its value is used.
247
246
248 * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir`
247 * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir`
249 is used. This function will first look at the :envvar:`IPYTHON_DIR`
248 is used. This function will first look at the :envvar:`IPYTHON_DIR`
250 environment variable and then default to the directory
249 environment variable and then default to the directory
251 :file:`$HOME/.ipython`.
250 :file:`$HOME/.ipython`.
252
251
253 For most users, the default value will simply be something like
252 For most users, the default value will simply be something like
254 :file:`$HOME/.ipython`.
253 :file:`$HOME/.ipython`.
255
254
256 Once the location of the IPython directory has been determined, you need to
255 Once the location of the IPython directory has been determined, you need to
257 know what filename to use for the configuration file. The basic idea is that
256 know what filename to use for the configuration file. The basic idea is that
258 each application has its own default configuration filename. The default named
257 each application has its own default configuration filename. The default named
259 used by the :command:`ipython` command line program is
258 used by the :command:`ipython` command line program is
260 :file:`ipython_config.py`. This value can be overriden by the ``-config_file``
259 :file:`ipython_config.py`. This value can be overriden by the ``-config_file``
261 command line flag. A sample :file:`ipython_config.py` file can be found
260 command line flag. A sample :file:`ipython_config.py` file can be found
262 in :mod:`IPython.config.default.ipython_config.py`. Simple copy it to your
261 in :mod:`IPython.config.default.ipython_config.py`. Simple copy it to your
263 IPython directory to begin using it.
262 IPython directory to begin using it.
264
263
265 .. _Profiles:
264 .. _Profiles:
266
265
267 Profiles
266 Profiles
268 ========
267 ========
269
268
270 A profile is simply a configuration file that follows a simple naming
269 A profile is simply a configuration file that follows a simple naming
271 convention and can be loaded using a simplified syntax. The idea is
270 convention and can be loaded using a simplified syntax. The idea is
272 that users often want to maintain a set of configuration files for different
271 that users often want to maintain a set of configuration files for different
273 purposes: one for doing numerical computing with NumPy and SciPy and
272 purposes: one for doing numerical computing with NumPy and SciPy and
274 another for doing symbolic computing with SymPy. Profiles make it easy
273 another for doing symbolic computing with SymPy. Profiles make it easy
275 to keep a separate configuration file for each of these purposes.
274 to keep a separate configuration file for each of these purposes.
276
275
277 Let's start by showing how a profile is used:
276 Let's start by showing how a profile is used:
278
277
279 .. code-block:: bash
278 .. code-block:: bash
280
279
281 $ ipython -p sympy
280 $ ipython -p sympy
282
281
283 This tells the :command:`ipython` command line program to get its
282 This tells the :command:`ipython` command line program to get its
284 configuration from the "sympy" profile. The search path for profiles is the
283 configuration from the "sympy" profile. The search path for profiles is the
285 same as that of regular configuration files. The only difference is that
284 same as that of regular configuration files. The only difference is that
286 profiles are named in a special way. In the case above, the "sympy" profile
285 profiles are named in a special way. In the case above, the "sympy" profile
287 would need to have the name :file:`ipython_config_sympy.py`.
286 would need to have the name :file:`ipython_config_sympy.py`.
288
287
289 The general pattern is this: simply add ``_profilename`` to the end of the
288 The general pattern is this: simply add ``_profilename`` to the end of the
290 normal configuration file name. Then load the profile by adding ``-p
289 normal configuration file name. Then load the profile by adding ``-p
291 profilename`` to your command line options.
290 profilename`` to your command line options.
292
291
293 IPython ships with some sample profiles in :mod:`IPython.config.profile`.
292 IPython ships with some sample profiles in :mod:`IPython.config.profile`.
294 Simply copy these to your IPython directory to begin using them.
293 Simply copy these to your IPython directory to begin using them.
295
294
296 Design requirements
295 Design requirements
297 ===================
296 ===================
298
297
299 Here are the main requirements we wanted our configuration system to have:
298 Here are the main requirements we wanted our configuration system to have:
300
299
301 * Support for hierarchical configuration information.
300 * Support for hierarchical configuration information.
302
301
303 * Full integration with command line option parsers. Often, you want to read
302 * Full integration with command line option parsers. Often, you want to read
304 a configuration file, but then override some of the values with command line
303 a configuration file, but then override some of the values with command line
305 options. Our configuration system automates this process and allows each
304 options. Our configuration system automates this process and allows each
306 command line option to be linked to a particular attribute in the
305 command line option to be linked to a particular attribute in the
307 configuration hierarchy that it will override.
306 configuration hierarchy that it will override.
308
307
309 * Configuration files that are themselves valid Python code. This accomplishes
308 * Configuration files that are themselves valid Python code. This accomplishes
310 many things. First, it becomes possible to put logic in your configuration
309 many things. First, it becomes possible to put logic in your configuration
311 files that sets attributes based on your operating system, network setup,
310 files that sets attributes based on your operating system, network setup,
312 Python version, etc. Second, Python has a super simple syntax for accessing
311 Python version, etc. Second, Python has a super simple syntax for accessing
313 hierarchical data structures, namely regular attribute access
312 hierarchical data structures, namely regular attribute access
314 (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to
313 (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to
315 import configuration attributes from one configuration file to another.
314 import configuration attributes from one configuration file to another.
316 Forth, even though Python is dynamically typed, it does have types that can
315 Forth, even though Python is dynamically typed, it does have types that can
317 be checked at runtime. Thus, a ``1`` in a config file is the integer '1',
316 be checked at runtime. Thus, a ``1`` in a config file is the integer '1',
318 while a ``'1'`` is a string.
317 while a ``'1'`` is a string.
319
318
320 * A fully automated method for getting the configuration information to the
319 * A fully automated method for getting the configuration information to the
321 classes that need it at runtime. Writing code that walks a configuration
320 classes that need it at runtime. Writing code that walks a configuration
322 hierarchy to extract a particular attribute is painful. When you have
321 hierarchy to extract a particular attribute is painful. When you have
323 complex configuration information with hundreds of attributes, this makes
322 complex configuration information with hundreds of attributes, this makes
324 you want to cry.
323 you want to cry.
325
324
326 * Type checking and validation that doesn't require the entire configuration
325 * Type checking and validation that doesn't require the entire configuration
327 hierarchy to be specified statically before runtime. Python is a very
326 hierarchy to be specified statically before runtime. Python is a very
328 dynamic language and you don't always know everything that needs to be
327 dynamic language and you don't always know everything that needs to be
329 configured when a program starts.
328 configured when a program starts.
330
329
331
General Comments 0
You need to be logged in to leave comments. Login now