Metadata-Version: 2.1
Name: metadict
Version: 0.1.3
Summary: MetaDict is a powerful dict subclass enabling (nested) attribute-style item access/assignment and IDE autocompletion support.
Home-page: https://github.com/LarsHill/metadict/
Author: Lars Hillebrand
Author-email: hokage555@web.de
License: Apache-2.0
Download-URL: https://github.com/LarsHill/metadict/
Description: <div align="center">
        <h1>MetaDict</h1>
        
        _Enabling dot notation and IDE autocompletion_
        
        <p align="center">
        <a href="#installation">Installation</a> •
          <a href="#features">Features</a> •
        <a href="#documentation">Documentation</a> •
          <a href="#competitors">Competitors</a> •
          <a href="#citation">Citation</a>
        </p>
        
        [![Python Version](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue.svg)](https://www.python.org/downloads/release/python-360/)
        [![PyPI version](https://badge.fury.io/py/metadict.svg?dummy=unused)](https://badge.fury.io/py/metadict)
        [![CircleCI](https://circleci.com/gh/LarsHill/metadict/tree/main.svg?style=shield)](https://circleci.com/gh/LarsHill/metadict/tree/main)
        [![codecov](https://codecov.io/gh/LarsHill/metadict/branch/main/graph/badge.svg?token=XG4UDWF8RE)](https://codecov.io/gh/LarsHill/metadict)
        [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
        
        </div>
        
        ---
        
        **MetaDict** is designed to behave exactly like a `dict` while enabling (nested) attribute-style key access/assignment with IDE autocompletion support. 
        
        Many libraries claim to do the same, but fail in different ways (see <a href="#competitors">Competitors</a>). 
        
        ## Installation
        
        ```bash
        $ pip install metadict
        ```
        ## Features
        
        - Attribute-style key access and assignment (dot notation) with IDE autocompletion support
           ```python
           from metadict import MetaDict
           
           cfg = MetaDict()
           cfg.optimizer = 'Adam'
           print(cfg.optimizer)
           >> Adam
           ```
           ![autocompletion demo](/autocompletion.png?raw=true "Autocompletion demo")
        - Nested key assignment similar to `defaultdict` from `collections`
           ```python
           cfg = MetaDict(nested_assignment=True)
           cfg.model.type = 'Transformer' 
           print(cfg.model.type)
           >> Transformer
           
           # or restrict nested assignment via context manager
           cfg = MetaDict()
           with cfg.enabling_nested_assignment() as cfg:
               cfg.model.type = 'Transformer'
           cfg.new_model.type = 'MLP'
           >> AttributeError: 'MetaDict' object has no attribute 'new_model'
           ```
        - Is a `dict`
           ```python
           dict_config = {'model': 'Transformer',
                          'optimizer': 'Adam'}    
           cfg = MetaDict(dict_config)
           print(isinstance(cfg, dict))
           >> True
           print(cfg == dict_config)
           >> True
           ```
        - Inbuilt `json` support
           ```python
           import json
               
           cfg = MetaDict({'model': 'Transformer'})
           print(json.loads(json.dumps(cfg)))
           >> {'model': 'Transformer'}
           ```
        - Recursive conversion to `dict`
           ```python  
           cfg = MetaDict({'models': [{'name': 'Transformer'}, {'name': 'MLP'}]})
           print(cfg.models[0].name)
           >> Transformer
           
           cfg_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))
           >> False
           
           cfg.models.append(MetaDict({'name': 'RNN'}))
           print(isinstance(cfg.models[-1], MetaDict))
           >> True
           ```
        - No namespace conflicts with inbuilt methods like `items()`, `update()`, etc.
           ```python  
           cfg = MetaDict()
           # Key 'items' is assigned as in a normal dict, but a UserWarning is raised
           cfg.items = [1, 2, 3]
           >> UserWarning: 'MetaDict' object uses 'items' internally. 'items' can only be accessed via `obj['items']`.
           print(cfg)
           >> {'items': [1, 2, 3]}
           print(cfg['items'])
           >> [1, 2, 3]
           
           # But the items method is not overwritten!
           print(cfg.items)
           >> <bound method Mapping.items of {'items': [1, 2, 3]}>
           print(list(cfg.items()))
           >> [('items', [1, 2, 3])]
           ```
        - References are preserved
           ```python
           params = [1, 2, 3]    
           cfg = MetaDict({'params': params})
           print(cfg.params is params)
           >> True
           
           model_dict = {'params': params}
           cfg = MetaDict(model=model_dict)
           print(cfg.model.params is params)
           >> True
           
           # Note: dicts are recursively converted to MetaDicts, thus...
           print(cfg.model is model_dict)
           >> False
           print(cfg.model == model_dict)
           >> True
           ```
        
        ## Documentation
        
        Check the [Test Cases](https://github.com/LarsHill/metadict/blob/main/tests/test_metadict.py) for a complete overview of all **MetaDict** features.
        
        
        ## Competitors
        - [Addict](https://github.com/mewwts/addict)
          - No key autocompletion in IDE
          - Nested key assignment cannot be turned off
          - Newly assigned `dict` objects are not converted to support attribute-style key access
          - Shadows inbuilt type `Dict`
        - [Prodict](https://github.com/ramazanpolat/prodict)
          - No key autocompletion in IDE without defining a static schema (similar to `dataclass`)
          - No recursive conversion of `dict` objects when embedded in `list` or other inbuilt iterables
        - [AttrDict](https://github.com/bcj/AttrDict)
          - No key autocompletion in IDE
          - Converts `list` objects to `tuple` behind the scenes
        - [Munch](https://github.com/Infinidat/munch)
          - Inbuilt methods like `items()`, `update()`, etc. can be overwritten with `obj.items = [1, 2, 3]` 
          - No recursive conversion of `dict` objects when embedded in `list` or other inbuilt iterables
        - [EasyDict](https://github.com/makinacorpus/easydict)
          - Only strings are valid keys, but `dict` accepts all hashable objects as keys
          - Inbuilt methods like `items()`, `update()`, etc. can be overwritten with `obj.items = [1, 2, 3]`
          - Inbuilt methods don't behave as expected: `obj.pop('unknown_key', None)` raises an `AttributeError`
        
        
        ## Citation
        
        ```
        @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}},
        }
        ```
        
Keywords: dict,attribute-style syntax,nesting,auto-completion
Platform: UNKNOWN
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: tests
