Giter Site home page Giter Site logo

easydict's Introduction

Easydict

EasyDict allows to access dict values as attributes (works recursively). A Javascript-like properties dot notation for python dicts.

INSTALL

pip install easydict

USAGE

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1

>>> d = edict(foo=3)
>>> d.foo
3

Very useful when exploiting parsed JSON content !

>>> from easydict import EasyDict as edict
>>> from simplejson import loads
>>> j = """{
"Buffer": 12,
"List1": [
    {"type" : "point", "coordinates" : [100.1,54.9] },
    {"type" : "point", "coordinates" : [109.4,65.1] },
    {"type" : "point", "coordinates" : [115.2,80.2] },
    {"type" : "point", "coordinates" : [150.9,97.8] }
]
}"""
>>> d = edict(loads(j))
>>> d.Buffer
12
>>> d.List1[0].coordinates[1]
54.9

Can set attributes as easily as getting them :

>>> d = EasyDict()
>>> d.foo = 3
>>> d.foo
3

It is still a dict !

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]

Instance and class attributes are accessed like usual objects...

>>> class Flower(EasyDict):
...     power = 1
...
>>> f = Flower({'height': 12})
>>> f.power
1
>>> f['power']
1

LICENSE

  • Lesser GNU Public License

AUTHORS

makinacom

Similar tools

easydict's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easydict's Issues

Is this library still under maintenance?

The latest version on pip is 1.9, which was released three years ago. Even there are still some new commits in this repo, why not release the newest version to pip?

RuntimeError: dictionary changed size during iteration?

pytorch ddp mode, dataloader wrapper batch data by EasyDict.
line 120, in init for k in self.class.dict.keys():

        # Class attributes
        for k in self.__class__.__dict__.keys():
            if not (k.startswith('__') and k.endswith('__')) and not k in ('update', 'pop'):
                setattr(self, k, getattr(self, k))
```python

Keeping the order

Hi,

is it possible to supply an OrderedDict and expect EasyDict to keep the order?

Thanks!

Where is the permute function gone?

Hi, I use a library that uses EasyDict and its permute function. When searching the internet I see that there once was a permute, but I can't find any information on where it is gone or if the function has been renamed. Can you give me a short hint?

Cannot use the dict() function to convert an easydict object to a regular dictionary

    good = {
        'node': {
            'type': 'activity',
            'id': 'nG6CFOqb4dQq',
            'diagramId': '4wwTVGk0mPhGtfDI',
            'renderKey': 'activity',
            'x': 180,
            'y': 200,
            'width': 100,
            'height': 60,
            'angle': 0,
            'attrs': {
                'body': {
                    'fill': 'none',
                    'stroke': 'none',
                    'refWidth': '100%',
                    'refHeight': '100%'
                },
                'fo': {
                    'refWidth': '100%',
                    'refHeight': '100%'
                },
                'label': {
                    'fontSize': 14,
                    'fill': '#333',
                    'refX': '50%',
                    'refY': '50%',
                    'textAnchor': 'middle',
                    'textVerticalAnchor': 'middle'
                },
                'shapeText': {
                    'verticalAlign': 'middle',
                    'textAlign': 'center',
                    'fill': '#000000',
                    'fontFamily': '宋体',
                    'fontSize': 12,
                    'lineHeight': 1.2,
                    'text': '活动',
                    'fontWeight': 'normal'
                },
                'shapeStyle': {
                    'strokeWidth': 1,
                    'fill': {
                        'startColor': '#89BCFF',
                        'endColor': '#C0DCFF',
                        'direction': 'to bottom'
                    },
                    'stroke': '#000000',
                    'strokeDasharray': '',
                    '3dEffect': False
                }
            },
            'extraProps': {},
            'ports': {
                'items': [{
                    'group': 'top',
                    'id': 'rrbr7WGHuRHq'
                }, {
                    'group': 'right',
                    'id': 'WCfPQPY3qVVs'
                }, {
                    'group': 'bottom',
                    'id': 'XxGbrm8p3ywp'
                }, {
                    'group': 'left',
                    'id': 'iVxkmHyURPG9'
                }],
                'groups': {
                    'top': {
                        'position': {
                            'name': 'top'
                        },
                        'zIndex': 10
                    },
                    'right': {
                        'position': {
                            'name': 'right'
                        },
                        'zIndex': 10
                    },
                    'bottom': {
                        'position': {
                            'name': 'bottom'
                        },
                        'zIndex': 10
                    },
                    'left': {
                        'position': {
                            'name': 'left'
                        },
                        'zIndex': 10
                    }
                }
            },
            'data': {
                'number': None,
                'desc': None,
                'category': None,
                'executionRole': {
                    'roleId': '2XfVV5q3IPik',
                    'roleText': '角色'
                },
                'keyActivity': None,
                'input': [{
                    'id': 3056,
                    'name': 'file_a.docx',
                    'nameEn': None,
                    'number': None,
                    'parentId': 3055,
                    'sortId': 0,
                    'type': 'STD_FILE',
                    'path': '3054-3055-3056-',
                    'namePath': '架构_batch_upload_files_process_001/流程图_batch_upload_files_process_001/file_a.docx',
                    'parentName': None,
                    'approvalStatus': None,
                    'isModified': None,
                    'hasChildren': None,
                    'isPublished': False,
                    'recordStatus': 0,
                    'level': 2,
                    'viewSort': '016100000000',
                    'isPublic': 0,
                    'extraProps': {
                        'relatedFileId': 3055
                    },
                    'processId': None,
                    'supportRiskDirId': None,
                    'institutionId': None,
                    'modifiedTime': None,
                    'supportFileDirId': 3055,
                    'deptId': None,
                    'pubTime': None
                }, {
                    'id': 3057,
                    'name': 'file_b.docx',
                    'nameEn': None,
                    'number': None,
                    'parentId': 3055,
                    'sortId': 1,
                    'type': 'STD_FILE',
                    'path': '3054-3055-3057-',
                    'namePath': '架构_batch_upload_files_process_001/流程图_batch_upload_files_process_001/file_b.docx',
                    'parentName': None,
                    'approvalStatus': None,
                    'isModified': None,
                    'hasChildren': None,
                    'isPublished': False,
                    'recordStatus': 0,
                    'level': 2,
                    'viewSort': '016100000001',
                    'isPublic': 0,
                    'extraProps': {
                        'relatedFileId': 3055
                    },
                    'processId': None,
                    'supportRiskDirId': None,
                    'institutionId': None,
                    'modifiedTime': None,
                    'supportFileDirId': 3055,
                    'deptId': None,
                    'pubTime': None
                }, {
                    'id': 3058,
                    'name': 'file_c.docx',
                    'nameEn': None,
                    'number': None,
                    'parentId': 3055,
                    'sortId': 2,
                    'type': 'STD_FILE',
                    'path': '3054-3055-3058-',
                    'namePath': '架构_batch_upload_files_process_001/流程图_batch_upload_files_process_001/file_c.docx',
                    'parentName': None,
                    'approvalStatus': None,
                    'isModified': None,
                    'hasChildren': None,
                    'isPublished': False,
                    'recordStatus': 0,
                    'level': 2,
                    'viewSort': '016100000002',
                    'isPublic': 0,
                    'extraProps': {
                        'relatedFileId': 3055
                    },
                    'processId': None,
                    'supportRiskDirId': None,
                    'institutionId': None,
                    'modifiedTime': None,
                    'supportFileDirId': 3055,
                    'deptId': None,
                    'pubTime': None
                }],
                'output': None,
                'sopList': [],
                'controlPoints': [],
                'standards': [],
                'indicators': [],
                'itSystems': [],
                'processingTimeLimit': None
            },
            'zIndex': 5
        }
    }
    print("kwargs: " + json.dumps(good))
    from easydict import EasyDict
    a = EasyDict(good)
    a = dict(a)
    print("kwargs: " + json.dumps(a))

#############################################
I think it will be a problem that needs to be solved because it is not possible to revert back to a regular dict, which may result in certain scenarios where other third-party libraries cannot be used. Because of the code design, sometimes I may need to first convert it to a regular dictionary, process it, and then revert back

python3.9 install easydict error

error:
`pip3.9 install easydict
Defaulting to user installation because normal site-packages is not writeable
Collecting easydict
Using cached easydict-1.10.tar.gz (6.4 kB)
Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error

× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [1 lines of output]
ERROR: Can not execute setup.py since setuptools is not available in the build environment.
[end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.`

How to fix ?

Add default_value support

Hi, I think easydict can add a default_value support, when we want to access some parameters, it can return the default_value we set.

    def __init__(self, d=None, default_value=None, **kwargs):
        self.__default_value = default_value
    def __getattr__(self, item):
        return self.__default_value

Working with non-stringable keys — lets allow it, but just dont set attributes.

Lets consider an example:

from easydict import EasyDict as edict

adict_widh_non_str_keys_and_dicts_inside = {
    ('Lon', 'Arn'): {'a':1, 'b':2},
    ('Lon', 'Gou'): {'a':3, 'b':4},
}

aedict = edict(adict_widh_non_str_keys_and_dicts_inside)

Now we get exception:

… /site-packages/easydict/__init__.py", line 122, in __init__
    setattr(self, k, v)
TypeError: attribute name must be string, not 'tuple'

Obviously there is not mapping/processing for «non-stringable» keys,
and it is OK for top dict
but we still need EasyDict to transform nested dicts, etc.

So would be be great if:

  • Just dont set attributes if key is nonstringable (one line patch try/except, or something)
  • provide optional mapping functions as (EasyDict parameter) for such keys.

Flatten unflatten easydict

Hi,
I am using easydict in my location prediction application.
I need to register the EasyDict as a pytree node with register_pytree_node
In order to do this I need to supply flatten and unflatten functions for easyDct.
Do you have code for flattening/unflattening easyDict. Could you give me an example?
Thanks,
AlexDonnini

EasyDict should wrap converted types instead of replacing them

When you assign a list, tuple or dict as a value in an EasyDict, it is replaced so that the attribute access works on children. This causes the object on LHS to no longer be in sync with the object on RHS:

a = EasyDict()
b = []
a.b = b
b.append(123)
a.b  # Expected: [123], actual: []

Methods like update() and pop() do not manage attributes correctly

Methods like update() and pop() do not have the results that I would expect. For example:

# Set up a dict.
In [14]: d = EasyDict(a=1, b=2)
In [15]: d.update(b=22, c=3)
In [16]: d.pop('a')

# This looks good.
In [17]: d
Out[17]: {'b': 22, 'c': 3}

# But attribute d.a is still present, even though we popped it.
In [18]: d.a
Out[18]: 1

# And the call to d.update() did not set up the d.c attribute.
In [19]: d.c
 ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-19-d731a153f8d9> in <module>()
----> 1 d.c
AttributeError: 'EasyDict' object has no attribute 'c'

Restore correct classes to lists and tuples

Currently, all tuples, lists and their subclasses are converted to lists, which is not ideal.
They should be converted back to their class/subclass (e.g. namedtuple).

BTW: why do you recurse down tuples/lists at all?

[suggestion] Better .get method

So, this is a simple suggestion, that I'm willing to contribute if more people believe it will be a good improvement:
We should be able to access sub-elements on a Easydict with the method .get() from dict. Now this is the current behavior:

> dic = EasyDict({"first":{"second":{"third":"value"}}})
> dic.first.second.get("third")
'value'
> dic.first.get("second.third")
None

I beleive the correct behavior should be something in this line:

> dic.first.get("second.third")
'value'

Any ideas or comments on this idea?

build whl for use in micropip

is it possible to switch to a more recent packaging system to allow easydict's use with micropip?

currently since no wheels are available the install fails.

ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

Python version: 3.6.5
OS: win10

pip install git+https://github.com/makinacorpus/easydict

Collecting git+https://github.com/makinacorpus/easydict
  Cloning https://github.com/makinacorpus/easydict to c:\users\owner\appdata\local\temp\pip-req-build-f7qokfq9
    ERROR: Command errored out with exit status 1:
     command: 'c:\users\owner\appdata\local\programs\python\python36\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\owner\\AppData\\Local\\Temp\\pip-req-build-f7qokfq9\\setup.py'"'"'; __file__='"'"'C:\\Users\\owner\\AppData\\Local\\Temp\\pip-req-build-f7qokfq9\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base 'C:\Users\owner\AppData\Local\Temp\pip-pip-egg-info-2s77kngi'
         cwd: C:\Users\owner\AppData\Local\Temp\pip-req-build-f7qokfq9\
    Complete output (28 lines):
    Traceback (most recent call last):
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\pkg_resources\__init__.py", line 2480, in resolve
        return functools.reduce(getattr, self.attrs, module)
    AttributeError: type object 'Distribution' has no attribute '_finalize_feature_opts'

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\owner\AppData\Local\Temp\pip-req-build-f7qokfq9\setup.py", line 30, in <module>
        'Programming Language :: Python :: 3.6'],
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\setuptools\__init__.py", line 163, in setup
        return distutils.core.setup(**attrs)
      File "c:\users\owner\appdata\local\programs\python\python36\lib\distutils\core.py", line 108, in setup
        _setup_distribution = dist = klass(attrs)
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\setuptools\dist.py", line 430, in __init__
        k: v for k, v in attrs.items()
      File "c:\users\owner\appdata\local\programs\python\python36\lib\distutils\dist.py", line 281, in __init__
        self.finalize_options()
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\setuptools\dist.py", line 720, in finalize_options
        for ep in sorted(eps, key=by_order):
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\setuptools\dist.py", line 719, in <lambda>
        eps = map(lambda e: e.load(), pkg_resources.iter_entry_points(group))
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\pkg_resources\__init__.py", line 2472, in load
        return self.resolve()
      File "c:\users\owner\appdata\local\programs\python\python36\lib\site-packages\pkg_resources\__init__.py", line 2482, in resolve
        raise ImportError(str(exc)) from exc
    ImportError: type object 'Distribution' has no attribute '_finalize_feature_opts'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

why make dict to self.__class__

    def __setattr__(self, name, value):
        if isinstance(value, (list, tuple)):
            value = [self.__class__(x)
                     if isinstance(x, dict) else x for x in value]
        elif isinstance(value, dict) and not isinstance(value, self.__class__):
            value = self.__class__(value)
        super(EasyDict, self).__setattr__(name, value)
        super(EasyDict, self).__setitem__(name, value)

I want to know why make dict to easydict.
I use the type dict of value , then this value can not use multiple gpu.

Unexpected default value for dict as class param

class IParserResult(EasyDict):
    cond: dict
    is_: set
    sortBy: str = "deck"
    desc: bool = False

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_ = set()


print(IParserResult(cond=dict()))

Gets {'cond': {'sortBy': 'deck', 'desc': False, 'is_': set()}, 'sortBy': 'deck', 'desc': False, 'is_': set()}

But,

@dc.dataclass
class IParserResult:
    cond: dict
    is_: set = dc.field(default_factory=set)
    sortBy: str = "deck"
    desc: bool = False


print(IParserResult(cond=dict()))

Gets IParserResult(cond={}, is_=set(), sortBy='deck', desc=False), with no recursion, at should be expected.

EasyDict converting tuple to list

While storing a tuple into the easydict, it is getting converted into a list. Is this by design?

Code to reproduce this behavior:

# Python version 3.6.8, easydict version 1.9, Windows OS
from easydict import EasyDict

d = dict()
d['my_tuple'] = (1, 2)
print(type(d['my_tuple']))
# Prints as expected: <class 'tuple'>

ed = EasyDict()
ed['my_tuple'] = (1, 2)
print(type(ed['my_tuple']))
# Prints unexpected: <class 'list'>

ed['my_set'] = {1, 2}
print(type(ed['my_set']))
# Prints as expected: <class 'set'>

With thanks to contributors for their work.

python3.6_easydict

@makinacorpus Thanks for your nice share! Could you please help me solve the issue?
when i use conda with python2.7, i can install easydict successfully. However,
when i use conda with python3.6, the log shows that

"UnsatisfiableError: The following specifications were found to be in conflict:

  • easydict -> python 2.7*
  • python 3.6*"

How can i install easydict with python3.6 . Thank you in advance!

RecursionError for inherited class from EasyDict

Environment

# uname -a
Linux 79407f72f74b 4.15.0-96-generic #97-Ubuntu SMP Wed Apr 1 03:25:46 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
# python --version
Python 3.7.4

What I want to do

>>> class A(EasyDict):
...     B = EasyDict()
...
>>> a = A()
>>>

What happens

>>> class A(EasyDict):
...     B = EasyDict()
...
>>> a = A()
.
.
.
    setattr(self, k, getattr(self, k))
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 129, in __setattr__
    value = self.__class__(value)
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 122, in __init__
    setattr(self, k, getattr(self, k))
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 129, in __setattr__
    value = self.__class__(value)
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 122, in __init__
    setattr(self, k, getattr(self, k))
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 129, in __setattr__
    value = self.__class__(value)
  File "/opt/conda/lib/python3.7/site-packages/easydict/__init__.py", line 120, in __init__
    for k in self.__class__.__dict__.keys():
RecursionError: maximum recursion depth exceeded while calling a Python object

setdefault not work

It's interesting that setdefault does not call __setitem__

from easydict import EasyDict

a = EasyDict()
a['a'] = a
print(a['a'])
print(a.a)
a.setdefault('b', 2)
print(a['b'])
print(a.b) # <--- AttributeError: 'EasyDict' object has no attribute 'b'

Fail to update the value!

I think this is an important problem when I debug a large project code. Finally I found it is caused by the weird characteristics easydict has. For example:

First, let's define a easydict instance.

>>> from easydict import EasyDict as edict
>>> C = edict()
>>> C.t = 1
>>> C
{'t': 1}
>>> C.t
1
>>> C['t']
1

Everything works well till now. Then let's update the value through the easydict style:

>>> C.t = 2
>>> C
{'t': 2}
>>> C.t
2
>>> C['t']
2

It seems everything goes well too. However, if we update the value with original dictionary style:

>>> C['t'] = 3
>>> C
{'t': 3}
>>> C.t
2
>>> C['t']
3

Find something strange? We could not access the value we want through easydict style. Actually, it seems that there exist two keyword of 't'. I do not know what happened. Could the author fix this problem? I think this will be really dangerous when using in big project.

Thanks a lot!

TypeError: __init__() takes 1 positional argument but 2 were given

System environment

python==3.6

easydict==1.9

import easydict

class A(easydict.EasyDict):
    def __init__(self):
        d = {"A": {"B": "C"}}
        super(A, self).__init__(d)
a = A()

TypeError: __init__() takes 1 positional argument but 2 were given
d = {"A": {"B": "C"}}
c = easydict.EasyDict(d)
print(c)

{"A": {"B": "C"}}

Is there any difference between these two, why does the first kind of error occur?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.