Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix in operator wrong behavior #41

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
64 changes: 18 additions & 46 deletions bunch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,6 @@ class Bunch(dict):
See unbunchify/Bunch.toDict, bunchify/Bunch.fromDict for notes about conversion.
"""

def __contains__(self, k):
""" >>> b = Bunch(ponies='are pretty!')
>>> 'ponies' in b
True
>>> 'foo' in b
False
>>> b['foo'] = 42
>>> 'foo' in b
True
>>> b.hello = 'hai'
>>> 'hello' in b
True
>>> b[None] = 123
>>> None in b
True
>>> b[False] = 456
>>> False in b
True
"""
try:
return dict.__contains__(self, k) or hasattr(self, k)
except:
return False

# only called if k not found in normal places
def __getattr__(self, k):
""" Gets key if it exists, otherwise throws AttributeError.
Expand All @@ -119,13 +95,9 @@ def __getattr__(self, k):
True
"""
try:
# Throws exception if not in prototype chain
return object.__getattribute__(self, k)
except AttributeError:
try:
return self[k]
except KeyError:
raise AttributeError(k)
return self[k]
except KeyError:
raise AttributeError(k)

def __setattr__(self, k, v):
""" Sets attribute k if it exists, otherwise sets key k. A KeyError
Expand All @@ -145,25 +117,25 @@ def __setattr__(self, k, v):
"""
try:
# Throws exception if not in prototype chain
object.__getattribute__(self, k)
dict.__getattribute__(self, k)
except AttributeError:
try:
self[k] = v
except:
raise AttributeError(k)
else:
object.__setattr__(self, k, v)
dict.__setattr__(self, k, v)

def __delattr__(self, k):
""" Deletes attribute k if it exists, otherwise deletes key k. A KeyError
raised by deleting the key--such as when the key is missing--will
propagate as an AttributeError instead.

>>> b = Bunch(lol=42)
>>> del b.values
>>> del b.values # doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError: 'Bunch' object attribute 'values' is read-only
AttributeError: ...values...
>>> del b.lol
>>> b.lol
Traceback (most recent call last):
Expand All @@ -172,21 +144,21 @@ def __delattr__(self, k):
"""
try:
# Throws exception if not in prototype chain
object.__getattribute__(self, k)
dict.__getattribute__(self, k)
except AttributeError:
try:
del self[k]
except KeyError:
raise AttributeError(k)
else:
object.__delattr__(self, k)
dict.__delattr__(self, k)

def toDict(self):
""" Recursively converts a bunch back into a dictionary.

>>> b = Bunch(foo=Bunch(lol=True), hello=42, ponies='are pretty!')
>>> b.toDict()
{'ponies': 'are pretty!', 'foo': {'lol': True}, 'hello': 42}
>>> b.toDict() == {'ponies': 'are pretty!', 'foo': {'lol': True}, 'hello': 42}
True

See unbunchify for more info.
"""
Expand Down Expand Up @@ -259,18 +231,18 @@ def unbunchify(x):
""" Recursively converts a Bunch into a dictionary.

>>> b = Bunch(foo=Bunch(lol=True), hello=42, ponies='are pretty!')
>>> unbunchify(b)
{'ponies': 'are pretty!', 'foo': {'lol': True}, 'hello': 42}
>>> unbunchify(b) == {'ponies': 'are pretty!', 'foo': {'lol': True}, 'hello': 42}
True

unbunchify will handle intermediary dicts, lists and tuples (as well as
their subclasses), but ymmv on custom datatypes.

>>> b = Bunch(foo=['bar', Bunch(lol=True)], hello=42,
... ponies=('are pretty!', Bunch(lies='are trouble!')))
>>> unbunchify(b) #doctest: +NORMALIZE_WHITESPACE
{'ponies': ('are pretty!', {'lies': 'are trouble!'}),
'foo': ['bar', {'lol': True}], 'hello': 42}
>>> unbunchify(b) == {'ponies': ('are pretty!', {'lies': 'are trouble!'}),
... 'foo': ['bar', {'lol': True}], 'hello': 42}
True

nb. As dicts are not hashable, they cannot be nested in sets/frozensets.
"""
if isinstance(x, dict):
Expand Down
4 changes: 2 additions & 2 deletions bunch/python3_compat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import platform
import sys

_IS_PYTHON_3 = (platform.version() >= '3')
_IS_PYTHON_3 = (sys.version_info[0] >= 3)

identity = lambda x : x

Expand Down