Package: dictmentor
dictmentorA python utility framework to augment dictionaries1.Installation2.Getting started3.Extensions3.1.Variables3.2.Environment3.3.ExternalResource3.4.ExternalYamlResource1. InstallationInstallation is straightforward via pip:pipinstalldictmentor2. Getting startedUsingdictmentoris simple. Just create an instance ofDictMentorand bind some extensions to it. The extensions
do the hard work augmenting the dictionary.DictMentordoes not have any extensions that are enabled by default. This
is because some extensions need some additional arguments passed that control their behaviour. If you bind no extensions
on your own and augment a dictionary, it will actually do nothing and return the dictionary as it is.Example usage:importosfromdictmentorimportDictMentor,extensionsasext,utilsbase_path=os.path.dirname(__file__)dm=DictMentor(ext.Environment(),ext.ExternalResource(base_path=base_path),ext.ExternalYamlResource(base_path=base_path))yml="""products:- external: item1.yaml- external: item2.yamlhome_directory: "{{env::HOME}}"extraction_sql: "{{external::products.sql}}""""withutils.modified_environ(HOME="/home/pi"):res=dm.load_yaml(yml)frompprintimportpprintpprint(res)# Result:# {'extraction_sql': '-- Contents of products.sql\nSELECT *\nFROM products\n;',#  'home_directory': '/home/pi',#  'products': [{'item1': {'price': 50, 'stock': 100}},#               {'item2': {'price': 99, 'stock': 10}}]}For a list of provided extensions please see the chapter Extensions. You can easily write your own extensions as well.
Please see existing extensions for a how-to.3. Extensions3.1. VariablesAugment the given dictionary by resolving pre-defined variables on the flyExample# Import DictMentor and extensionsimportdictmentor.extensionsasextfromdictmentorimportDictMentor,utilsyml="""statements:my_env: "{{var::my_env}}"home: "{{var::home}}"unknown: "{{var::unknown}}"combined: "{{var::my_env}}@{{var::home}}""""var_ext=ext.Variables(my_env='development',home="/home/pi",)result=DictMentor().bind(var_ext).load_yaml(yml)frompprintimportpprintpprint(result)# Result:# {'statements': {'combined': 'development@/home/pi',#                 'home': '/home/pi',#                 'my_env': 'development',#                 'unknown': 'none'}}3.2. EnvironmentAugment the given dictionary by resolving environment variables on the flyExample# Import DictMentor and extensionsimportdictmentor.extensionsasextfromdictmentorimportDictMentor,utilsyml="""statements:my_env: "{{env::MY_ENV}}"home: "{{env::HOME}}"unknown: "{{env::UNKNOWN}}"with_default: "{{env::UNKNOWN:=the_default}}""""# Make sure that MY_ENV is set and that UNKNOWN is unsetwithutils.modified_environ("UNKNOWN",MY_ENV='development'):result=DictMentor().bind(ext.Environment()).load_yaml(yml)frompprintimportpprintpprint(result)# Result:# {'statements': {'home': '/home/pi',#                 'my_env': 'development',#                 'unknown': 'none'#                 'with_default': 'the_default'}}3.3. ExternalResourceAugment the given dictionary by resolving files on disk (whether absolute or relative) and integrating their content.
If the path to the file is specified in a relative manner you should pass abase_pathto theExternalResourceinstance when instantiating it. Otherwise the current working directory will be assumed.Example-- Contents of all.sqlSELECT*FROMfoo;-- Contents of single.sqlSELECT*FROMfooWHEREid={placeholder};# Import DictMentor and extensionsimportdictmentor.extensionsasextfromdictmentorimportDictMentorimportosbase_path=os.path.dirname(__file__)yml="""statements:all: "{{external::all.sql}}"single: "{{external::single.sql}}""""result=DictMentor().bind(ext.ExternalResource(base_path)).load_yaml(yml)frompprintimportpprintpprint(result)# Result:# {'statements': {'all': '-- Contents of all.sql\nSELECT *\nFROM foo\n;',#                 'single': '-- Contents of single.sql\nSELECT *\nFROM foo\nWHERE id = {placeholder}\n;'}}3.4. ExternalYamlResourceAugment the given dictionary by resolving by yaml file on disk (whether absolute or relative) and integrating
its content (as a dictionary) as the current node. The yaml's contents will be augmented as well.If the path to the file is specified in a relative manner you should pass abase_pathto theExternalYamlResourceinstance when instantiating it. Otherwise the current working directory will be assumed.Example# Contents of inner.yamlinner:item1:item2:external:item3.yaml# Contents of item3.yamlitem2:price:50# You may also update nodes from the parent nodeitem3:price:100count:5sold:200# Import DictMentor and extensionsimportdictmentor.extensionsasextfromdictmentorimportDictMentorimportosbase_path=os.path.dirname(__file__)yml="""statements:external: "inner.yaml""""result=DictMentor().bind(ext.ExternalYamlResource(base_path=base_path)).load_yaml(yml)frompprintimportpprintpprint(result)# Result:# {'statements': {'inner': {'item1': None,#                           'item2': {'price': 50},#                           'item3': {'count': 5, 'price': 100, 'sold': 200}}}}