Package: metadict
MetaDictEnabling dot notation and IDE autocompletionInstallation•Features•Documentation•Competitors•CitationMetaDictis designed to behave exactly like adictwhile enabling (nested) attribute-style key access/assignment with IDE autocompletion support.Many libraries claim to do the same, but fail in different ways (seeCompetitors).Installation$pipinstallmetadictFeaturesAttribute-style key access and assignment (dot notation) with IDE autocompletion supportfrommetadictimportMetaDictcfg=MetaDict()cfg.optimizer='Adam'print(cfg.optimizer)>>AdamNested key assignment similar todefaultdictfromcollectionscfg=MetaDict(nested_assignment=True)cfg.model.type='Transformer'print(cfg.model.type)>>Transformer# or restrict nested assignment via context managercfg=MetaDict()withcfg.enabling_nested_assignment()ascfg:cfg.model.type='Transformer'cfg.new_model.type='MLP'>>AttributeError:'MetaDict'objecthasnoattribute'new_model'Is adictdict_config={'model':'Transformer','optimizer':'Adam'}cfg=MetaDict(dict_config)print(isinstance(cfg,dict))>>Trueprint(cfg==dict_config)>>TrueInbuiltjsonsupportimportjsoncfg=MetaDict({'model':'Transformer'})print(json.loads(json.dumps(cfg)))>>{'model':'Transformer'}Recursive conversion todictcfg=MetaDict({'models':[{'name':'Transformer'},{'name':'MLP'}]})print(cfg.models[0].name)>>Transformercfg_dict=cfg.to_dict()print(type(cfg_dict['models'][0]))>><class'dict'># Note: Appending a `dict` to a list within a `MetaDict` does not convert the `dict`.# MetaDict does not overwrite `list` so intercepting `append`. `extend`, etc. is currently not possible.# Simply wrap the appended or extended `dict` as a `MetaDict`.cfg.models.append({'name':'RNN'})print(isinstance(cfg.models[-1],MetaDict))>>Falsecfg.models.append(MetaDict({'name':'RNN'}))print(isinstance(cfg.models[-1],MetaDict))>>TrueNo namespace conflicts with inbuilt methods likeitems(),update(), etc.cfg=MetaDict()# Key 'items' is assigned as in a normal dict, but a UserWarning is raisedcfg.items=[1,2,3]>>UserWarning:'MetaDict'objectuses'items'internally.'items'canonlybeaccessedvia`obj['items']`.print(cfg)>>{'items':[1,2,3]}print(cfg['items'])>>[1,2,3]# But the items method is not overwritten!print(cfg.items)>><boundmethodMapping.itemsof{'items':[1,2,3]}>print(list(cfg.items()))>>[('items',[1,2,3])]References are preservedparams=[1,2,3]cfg=MetaDict({'params':params})print(cfg.paramsisparams)>>Truemodel_dict={'params':params}cfg=MetaDict(model=model_dict)print(cfg.model.paramsisparams)>>True# Note: dicts are recursively converted to MetaDicts, thus...print(cfg.modelismodel_dict)>>Falseprint(cfg.model==model_dict)>>TrueDocumentationCheck theTest Casesfor a complete overview of allMetaDictfeatures.CompetitorsAddictNo key autocompletion in IDENested key assignment cannot be turned offNewly assigneddictobjects are not converted to support attribute-style key accessShadows inbuilt typeDictProdictNo key autocompletion in IDE without defining a static schema (similar todataclass)No recursive conversion ofdictobjects when embedded inlistor other inbuilt iterablesAttrDictNo key autocompletion in IDEConvertslistobjects totuplebehind the scenesMunchInbuilt methods likeitems(),update(), etc. can be overwritten withobj.items = [1, 2, 3]No recursive conversion ofdictobjects when embedded inlistor other inbuilt iterablesEasyDictOnly strings are valid keys, butdictaccepts all hashable objects as keysInbuilt methods likeitems(),update(), etc. can be overwritten withobj.items = [1, 2, 3]Inbuilt methods don't behave as expected:obj.pop('unknown_key', None)raises anAttributeErrorCitation@article{metadict,
  title = {MetaDict - Enabling dot notation and IDE autocompletion},
  author = {Hillebrand, Lars},
  year = {2022},
  publisher = {GitHub},
  journal = {GitHub repository},
  howpublished = {\url{https://github.com/LarsHill/metadict}},
}