Skip to content

Commit 2dcba80

Browse files
committed
add extras module with extras.attrs.AttribDictable
1 parent 2ac1a2e commit 2dcba80

3 files changed

Lines changed: 83 additions & 0 deletions

File tree

privex/helpers/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@
102102
except ImportError:
103103
log.debug('privex.helpers __init__ failed to import "setuppy.bump", not loading packaging helpers')
104104

105+
try:
106+
from privex.helpers.extras import *
107+
except ImportError:
108+
log.debug('privex.helpers __init__ failed to import "extras", cannot load any extras.* modules...')
109+
105110

106111
def _setup_logging(level=logging.WARNING):
107112
"""

privex/helpers/extras/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
Various helper functions/classes which depend on a certain package being installed.
3+
4+
This constructor file attempts to load each extras module individually, each wrapped with a try/catch
5+
for :class:`ImportError` so that one unavailable package doesn't cause problems.
6+
7+
"""
8+
import logging
9+
10+
log = logging.getLogger(__name__)
11+
12+
__all__ = ['HAS_ATTRS']
13+
HAS_ATTRS = False
14+
15+
try:
16+
from privex.helpers.extras.attrs import *
17+
HAS_ATTRS = True
18+
__all__ += ['AttribDictable']
19+
except ImportError:
20+
log.debug('privex.helpers.extras __init__ failed to import "attrs", not loading attrs library helpers')
21+
22+
23+
24+

privex/helpers/extras/attrs.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import attr
2+
3+
__all__ = [
4+
'AttribDictable'
5+
]
6+
7+
8+
@attr.s
9+
class AttribDictable:
10+
"""
11+
A small mixin class for :py:func:`attr.s` classes, allowing them to behave like dictionaries, and
12+
support casting into dictionaries using ``dict(x)``.
13+
14+
Usage::
15+
16+
>>> import attr
17+
>>> from privex.helpers import AttribDictable
18+
>>>
19+
>>> @attr.s
20+
>>> class Example(AttribDictable):
21+
... hello = attr.ib(type=str)
22+
... testing = attr.ib(type=bool, default=True)
23+
...
24+
>>> x = Example(hello='world')
25+
>>> x['hello']
26+
'world'
27+
>>> x['hello'] = 'lorem ipsum'
28+
>>> dict(x)
29+
{'hello': 'lorem ipsum', 'testing': True}
30+
31+
32+
"""
33+
def get(self, key, default=None):
34+
try:
35+
return self[key]
36+
except KeyError:
37+
return default
38+
39+
def __iter__(self):
40+
"""Handle casting via ``dict(myclass)``"""
41+
for k, v in attr.asdict(self).items():
42+
yield k, v
43+
44+
def __getitem__(self, key):
45+
"""
46+
When the instance is accessed like a dict, try returning the matching attribute.
47+
If the attribute doesn't exist, raise :class:`KeyError`
48+
"""
49+
if hasattr(self, key):
50+
return getattr(self, key)
51+
raise KeyError(key)
52+
53+
def __setitem__(self, key, value):
54+
return setattr(self, key, value)

0 commit comments

Comments
 (0)