Giter VIP home page Giter VIP logo

attrdict's People

Contributors

bcj avatar digenis avatar donsignore avatar eukaryote avatar jtratner avatar

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

attrdict's Issues

Provide both attrdict.AttrMapping & attrdict.AttrDict?

Given that there seems to be continued interest in a closer matching to dict, I may be convinced that attrdict should provide both an AttrMapping which reflects current AttrDict and an AttrDict that subclasses dict. Would this be a satisfactory solution for those wishing AttrDict more-closely reflected dict?

This would have to be a major-version change since it could easily effect people using this in prod.

AttrDict is not a dict

The project description ready:

A dictionary that allows attribute-style access.

However, I discovered:

> from attrdict import AttrDict
> a = AttrDict()
> isinstance(a, dict)
False

Is there a reason AttrDict is not extending dict? It also makes it impossible to use AttrDict as a "drop in" replacement in existing APIs.
Consider an API that used to return (or receive) a dict and could be switched to an AttrDict.

Override __dir__ to allow for tab completion in ipython and easier inspection

The common thing to do if you override __getattr__ is to also override __dir__ like so:

def __dir__(self):
    # you may also want to filter the keys to only include the strings
    return sorted(set(super(AttrDict, self).__dir__()) + set(self.keys()))

This would make it much easier to use attrdict in IPython and other IDEs as you would gain auto-completion.

Property validation in __init__ method makes conclision

Hello bcj,
When i pass {'get': 'example'} to __init__ method, instance created, but i cant access dict key by getattr since __init__ method only add no-conflict key as instance property.

But when i user attrdict_instance.property = "example", it raise a key error.

The question is : this two place acts not the same way.(__init__ and setattr)

Dict has key get but i can't access it(if i haven't read source code , i wouldn't know how can i access it correctly.)

Would __init__ method raises a KeyError to tell user do not use reserved key-name when collision being caught be a better way?

Best wishes:)

recursive converts all Sequences to lists

If Recursive mode is set, all Sequences will be converted into a list by build

e.g.:

>>> adict = Attrdict({'foo': ({'bar': 'baz'}, {'lorem': 'ipsum'})
>>> isinstance(adict.foo, list)
True

The Sequence's type should be grabbed from the object.

immutable AttrDict instances

I find I need an immutable mapping fairly often. Would it be reasonable to add an attrdict.FrozenAttrDict class that supports __hash__?

Use apache or mit license

I'd like to try to use your project but the licensing has me worried. Is it possible to change to a MIT or apache 2.0 license instead of your personal license?

Pulling a list of dicts from AttrDict results in just a list of dicts.

As the title states, just a list of regular dicts instead of AttrDicts. Here is a workaround.

def deep_attrdict(d: dict) -> AttrDict:
    """Uses recursion to dive deep into the dict
    and convert all dict types to type AttrDict. This will 
    eliminate the bug where pulling a list of dicts 
    out of an AttrDict results in just a list of dicts.
    """
    d = AttrDict(d)
    for k, v in d.items():
        if isinstance(v, dict):
            d[k] = deep_attrdict(v)
        elif isinstance(v, list):
            for i, item in enumerate(v):
                if isinstance(item, dict):
                    v[i] = deep_attrdict(item)
    return d

Nested AttrDicts don't work

In [17]: a = AttrDict()

In [18]: a.b = AttrDict()

In [19]: a.b.c = "Hi there"

In [20]: a
Out[20]: AttrDict({'b': AttrDict({})})

In [21]: a.b
Out[21]: AttrDict({})

In [22]: a.b.c
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-22-d34de4f2be62> in <module>()
----> 1 a.b.c

/usr/local/lib/python2.7/dist-packages/attrdict/mixins.pyc in __getattr__(self, key)
     80             raise AttributeError(
     81                 "'{cls}' instance has no attribute '{name}'".format(
---> 82                     cls=self.__class__.__name__, name=key
     83                 )
     84             )

AttributeError: 'AttrDict' instance has no attribute 'c'

Recusion problem

Really like this module.
I have code that uses the old UserDict which has a .data attribute. My code uses that a lot.
My old code uses stuff like:
theImportantData = UserDict()
.. then initialize stuff and then...
theItem = theImportantData.data["NAME"]

(Don't ask me why I liked it, I just did... )

But when I tried to subclass AttrDict like this

class newAttrDict(AttrDict):
    def __init__(self):
        self.data = self

to be able to get access to the theImportantData.data attribute,
I get this:

 File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
  File "/usr/local/lib/python3.4/site-packages/attrdict/__init__.py", line 115, in __getattr__
    if self._default_factory is None or key.startswith('_'):
RuntimeError: maximum recursion depth exceeded while calling a Python object

Anyway thanks for a nice addition to the Dict class.
It might be nice just to have a .data attribute like the old UserDict, instead of playing around with _mapping .

Thanks,

Mike

AttrDict does not provide simple constructor

This somewhat relates to #18, but I would like to raise this issue independently.

> dict(a=23) == dict(dict(a=23))
True

> AttrDict(a=23) == AttrDict(dict(a=23))
...
TypeError: __init__() got an unexpected keyword argument 'a'

The **kwargs based constructor of dict is incredibly helpful.

AttrDict doesn't implement copy()

I'm using AttrDict as the dict type for ConfigParser and found that it doesn't implement the copy() method, which ConfigParser uses when calling get() to retrieve a config field.

In my use case I extended AttrDict to implement this method. It would be nice to have this in upstream though.

class AttrDict(attrdict.AttrDict):
    def copy(self):
        return self._mapping.copy()

Or to patch it only if it doesn't exist:

if not hasattr(AttrDict, "copy"):
    setattr(AttrDict, "copy", lambda self: self._mapping.copy())

AttrDict.get() does not return AttrDict but dict on nested AttrDicts

Hello everyone,

test = AttrDict({"a": {"b": "c"}})
type(test.a)
<class 'attrdict.AttrDict'>
type(test.get("a"))
<type 'dict'>

Is this behavior wanted or do you think as well that it is something worth changing?

As a workaround I am using: a = test.a if "a" in test else None

Best regards and thank you for this module,
Tim

100% Test Coverage

Issue 4 was the result of not enough testing. Get 100% coverage (plus the badge)

Dict access does not return a dict

This example is shown:

> a = AttrDict({'foo': {'bar': 'baz'}})
> a.foo.bar
'baz'
> a['foo'].bar
AttributeError: 'dict' object has no attribute 'bar'

This is not the case. a['foo'] is still an AttrDict and a['foo'].bar will happily return 'baz'.

Empty list becomes a tuple in AttrDict

In Python 3.5 with attrdict 2.0.0

first_dict = AttrDict()
first_dict.second_list = list()
for i in range(10):
    first_dict.second_list.append(i)
print("Debug dict. Attr dict01: '{}'".format(first_dict))

Gives

AttributeError: 'tuple' object has no attribute 'append'

It looks like AttrDict converts empty lists into tuples.

Use variable values in dotted notation?

Is there a way to use variables in the middle of a dotted phrase?

name = 'foo'
indict = {name: "name's value"}
adict = AttrDict(indict)

print adict.foo # works
print adict.name # fails, with AttributeError, because it's looking for `name` and not `foo`

list are not handled properly

List are not handled properly
Example:

d = AttrDict({"a": 1, "b": 2, "c": {"d": 3, "e": [4, 5, {"f": 6, "g": 7}]}})
d.c.e[2].f  # AttributeError: 'dict' object has no attribute 'f'

_build method can be changed like this:

  if isinstance(obj, Mapping):
     return obj
  if isinstance(obj, list):
     return [cls._build() for o in obj]
  return obj

feature request: copy() to get a new copy (as dict?)

Please support deep-copy for creating an exact non-shared copy of the object (or a branch of it).
Preferably as a method of AttrDict, as the dict object.

e.g.

def copy(self, item=None):
    if item:
        obj = self.get(item, None)
        if obj is None:
            return None
        if type(obj) is list:
            return list(obj)
        if type(obj) is dict:
            return AttrDict2(dict(obj))
        return obj
    else:
        return AttrDict2(dict(self))

Using the "recursive" param shouldn't show "recursive" as an attribute

The recursive parameter shouldn't modify the contents of the object.

>>> attrdict.AttrDict({'list': [{'value': 1}, {'value': 2}]}, recursive=False)
AttrDict({'list': [{'value': 1}, {'value': 2}], 'recursive': False})

Let's say I have an AttrDict object for which my keys should be all numbers. Recursive should not be added to the keys.

>>> ad=attrdict.AttrDict({1: 'one', 2: 'two'}, recursive=False)
>>> ad.keys()
dict_keys([1, 2, 'recursive'])

Bugs in doc examples

Hi!

There seem to be two bugs in the examples.

First, this example right off the docs

> attr = AttrDict({'foo': [{'bar': 'baz'}, {'bar': 'qux'}]})
> for sub_attr in attr.foo:
>     print(subattr.foo)
'baz'
'qux'

gets me NameError: name 'subattr' is not defined because of the missing underscore in subattr but it's also foo a second time, while it would need to be bar, i.e. making print(sub_attr.bar) for the body of the loop.

Further down the docs read:

> adict = AttrDict({'list': [{'value': 1}, {'value': 2}]}, recursive=False)
> for element in adict.list:
>     isinstance(element, AttrDict)
False
False

But in ipython (with Python 2.7.13), I get this, instead:

In [29]: adict = AttrDict({'list': [{'value': 1}, {'value': 2}]}, recursive=False)

In [31]: [isinstance(element, AttrDict) for element in adict.list]
Out[31]: [True, True]  # ???

I am unsure if recursive=False is not working as expected or if just the example is broken. Please enlighten me. Thanks!

PS: The second example seems to also miss use of print(...) for the examples to be consistent to each other.

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.