2
This file is part of lazr.config.
4
lazr.config is free software: you can redistribute it and/or modify it
5
under the terms of the GNU Lesser General Public License as published by
6
the Free Software Foundation, either version 3 of the License, or (at your
7
option) any later version.
9
lazr.config is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12
License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with lazr.config. If not, see <http://www.gnu.org/licenses/>.
79
96
>>> schema.filename
80
97
'...lazr/config/testdata/base.conf'
99
If you provide an optional file-like object as a second argument to the
100
constructor, that is used instead of opening the named file implicitly.
102
>>> file_object = open(base_conf)
103
>>> other_schema = ConfigSchema('/does/not/exist.conf', file_object)
104
>>> verifyObject(IConfigSchema, other_schema)
107
>>> print other_schema.name
109
>>> print other_schema.filename
112
>>> file_object.close()
82
114
A schema is made up of multiple SchemaSections. They can be iterated
83
115
over in a loop as needed.
127
>>> for section_schema in sorted(other_schema, key=attrgetter('name')):
128
... print section_schema.name
95
136
You can check if the schema contains a section name, and that can be
96
137
used to access the SchemaSection as a subscript.
368
419
# Accept the default values for the optional section-5.
422
The .master section allows admins to define configurations for an arbitrary
423
number of processes. If the schema defines .master sections, then the conf
424
file can contain sections that extend the .master section. These are like
425
categories with templates except that the section names extending .master need
426
not be named in the schema file.
428
>>> master_schema_conf = path.join(testfiles_dir, 'master.conf')
429
>>> master_local_conf = path.join(testfiles_dir, 'master-local.conf')
430
>>> master_schema = ConfigSchema(master_schema_conf)
431
>>> sections = master_schema.getByCategory('thing')
432
>>> sorted(section.name for section in sections)
434
>>> master_conf = master_schema.load(master_local_conf)
435
>>> sections = master_conf.getByCategory('thing')
436
>>> sorted(section.name for section in sections)
437
['thing.one', 'thing.two']
438
>>> sorted(section.foo for section in sections)
440
>>> print master_conf.thing.one.name
371
443
The shared.conf file derives the keys and default values from the
372
444
schema. This config was loaded before local.conf because its sections
373
445
and values are required to be in place before local.conf applies its
774
857
key4 : Fc;k yeah!
860
push() can also be used to extend master sections.
862
>>> sections = sorted(master_conf.getByCategory('bar'),
863
... key=attrgetter('name'))
864
>>> for section in sections:
865
... print section.name, section.baz
869
>>> master_conf.push('override', """
873
>>> sections = sorted(master_conf.getByCategory('bar'),
874
... key=attrgetter('name'))
875
>>> for section in sections:
876
... print section.name, section.baz
880
>>> master_conf.push('overlord', """
884
>>> sections = sorted(master_conf.getByCategory('bar'),
885
... key=attrgetter('name'))
886
>>> for section in sections:
887
... print section.name, section.baz
892
push() works with master sections too.
894
>>> schema_file = StringIO.StringIO("""\
899
>>> push_schema = ConfigSchema('schema.cfg', schema_file)
901
>>> config_file = StringIO.StringIO("""\
905
>>> push_config = push_schema.loadFile(config_file, 'config.cfg')
906
>>> print push_config.thing.one.foo
908
>>> print push_config.thing.one.bar
911
>>> push_config.push('test.cfg', """\
915
>>> print push_config.thing.one.foo
917
>>> print push_config.thing.one.bar
1048
1194
functions have to be imported and called explicitly on the configuration
1049
1195
variable values.
1201
There is a helper for turning various strings into the boolean values True and
1204
>>> from lazr.config import as_boolean
1206
True values include (case-insensitively): true, yes, 1, on, enabled, and
1209
>>> for value in ('true', 'yes', 'on', 'enable', 'enabled', '1'):
1210
... print value, '->', as_boolean(value)
1211
... print value.upper(), '->', as_boolean(value.upper())
1225
False values include (case-insensitively): false, no, 0, off, disabled, and
1228
>>> for value in ('false', 'no', 'off', 'disable', 'disabled', '0'):
1229
... print value, '->', as_boolean(value)
1230
... print value.upper(), '->', as_boolean(value.upper())
1244
Anything else is a error.
1246
>>> as_boolean('cheese')
1247
Traceback (most recent call last):
1249
ValueError: Invalid boolean value: cheese
1209
1412
Traceback (most recent call last):
1420
It's convenient to be able to use symbolic log level names when using
1421
lazr.config to configure the Python logger.
1423
>>> from lazr.config import as_log_level
1425
Any symbolic log level value is valid to use, case insensitively.
1427
>>> for value in ('critical', 'error', 'warning', 'info',
1428
... 'debug', 'notset'):
1429
... print value, '->', as_log_level(value)
1430
... print value.upper(), '->', as_log_level(value.upper())
1444
Non-log levels cannot be used here.
1446
>>> as_log_level('cheese')
1447
Traceback (most recent call last):
1449
AttributeError: 'module' object has no attribute 'CHEESE'