This repository has been archived by the owner on Feb 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Configuration declaration parser rewritten:
* empty list is interpreted as a default value of list type item * empty dictionary is interpreted as a default value of a dict type item * list of anything but tuples is treated as a default value of list type item * no more class-based configurations * no more free-floating Item() instances in lists used for section declaration -- must be a tuple.
- Loading branch information
Showing
11 changed files
with
288 additions
and
308 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import collections | ||
import inspect | ||
|
||
import six | ||
|
||
from configmanager.base import BaseItem, BaseSection | ||
|
||
|
||
def parse_config_declaration(declaration, parent_section=None, root=None): | ||
|
||
# Pass _configmanager_settings through so we know how to create new items/sections | ||
# Process declaration recursively (unlike the old parser) | ||
# Don't allow much freedom into what is accepted | ||
# Sequences (excluding strings) and mappings (excluding our base types) have special meaning and | ||
# cannot be used as default values unless wrapped inside Item. | ||
|
||
if root: | ||
parent_section = root | ||
|
||
is_valid_config_root_declaration = ( | ||
inspect.ismodule(declaration) | ||
or | ||
( | ||
isinstance(declaration, collections.Sequence) | ||
and len(declaration) > 0 | ||
and isinstance(declaration[0], tuple) | ||
) | ||
or | ||
( | ||
isinstance(declaration, collections.Mapping) | ||
and len(declaration) > 0 | ||
) | ||
) | ||
if not is_valid_config_root_declaration: | ||
raise ValueError( | ||
'Config root declaration has to be a module, a non-empty sequence, or non-empty mapping, ' | ||
'got a {}'.format(type(declaration)), | ||
) | ||
|
||
if isinstance(declaration, (BaseItem, BaseSection)): | ||
# Do not parse existing objects of our hierarchy | ||
# TODO However, we should probably process raw sections! | ||
# TODO Also, how would it be possible for user to legally create a new Section? | ||
return declaration | ||
|
||
elif inspect.ismodule(declaration): | ||
return parse_config_declaration(declaration.__dict__, parent_section=parent_section, root=root) | ||
|
||
elif isinstance(declaration, collections.Mapping): | ||
|
||
if len(declaration) == 0: | ||
# Empty dictionary means an empty item | ||
return parent_section.create_item(default=declaration) | ||
|
||
# Create a list of tuples so we can use the standard declaration parser below | ||
return parse_config_declaration([x for x in declaration.items()], parent_section=parent_section, root=root) | ||
|
||
if isinstance(declaration, collections.Sequence) and not isinstance(declaration, six.string_types): | ||
|
||
if len(declaration) == 0 or not isinstance(declaration[0], tuple): | ||
# Declaration of an item | ||
return parent_section.create_item(default=declaration) | ||
|
||
# Pre-process all keys and discard private parts and separate out meta parts | ||
clean_declaration = [] | ||
meta = {} | ||
|
||
for k, v in declaration: | ||
if k.startswith('_'): | ||
continue | ||
elif k.startswith('@'): | ||
meta[k[1:]] = v | ||
continue | ||
clean_declaration.append((k, v)) | ||
|
||
if not clean_declaration or meta.get('type'): | ||
# Must be an item | ||
if not clean_declaration: | ||
return parent_section.create_item(**meta) | ||
else: | ||
meta['default'] = dict(clean_declaration) | ||
return parent_section.create_item(**meta) | ||
|
||
section = root or parent_section.create_section() | ||
|
||
for k, v in clean_declaration: | ||
obj = parse_config_declaration(v, parent_section=section) | ||
if obj.is_section: | ||
section.add_section(k, obj) | ||
else: | ||
section.add_item(k, obj) | ||
|
||
return section | ||
|
||
# Declaration of an item | ||
return parent_section.create_item(default=declaration) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.