Skip to content
This repository has been archived by the owner on Oct 3, 2019. It is now read-only.

Commit

Permalink
Dictionary/List subclass their native types
Browse files Browse the repository at this point in the history
  • Loading branch information
jacebrowning committed Dec 30, 2014
1 parent 1f4062d commit b2faffd
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
18 changes: 9 additions & 9 deletions yorm/container.py
Expand Up @@ -17,32 +17,32 @@ def __init__(cls, name, bases, nmspc):
cls.yorm_attrs = {}


class _dict(dict):
class AttributeDict(dict):

"""A `dict` with keys available as attributes."""

def __init__(self, *args, **kwargs):
super(dict2, self).__init__(*args, **kwargs)
super(AttributeDict, self).__init__(*args, **kwargs)
self.__dict__ = self


class Dictionary(dict, metaclass=ContainerMeta):
class Dictionary(AttributeDict, metaclass=ContainerMeta):

"""Base class for a dictionary of attribute converters."""

TYPE = _dict

@classmethod
def to_value(cls, obj): # pylint: disable=E0213
"""Convert all loaded values back to its original attribute types."""
if cls is Dictionary:
msg = "Dictionary class must be subclassed to use"
raise NotImplementedError(msg)

value = cls.TYPE()
yorm_attrs = cls.yorm_attrs.copy()
# Create an uninitialized object with keys as attributes
value = cls.__new__(cls)
value.__dict__ = value

# Convert object attributes to a dictionary
yorm_attrs = cls.yorm_attrs.copy()
if isinstance(obj, cls):
items = obj.__dict__.items()
dictionary = {k: v for k, v in items if k in yorm_attrs}
Expand Down Expand Up @@ -107,7 +107,7 @@ def to_dict(obj):
return {}


class List(metaclass=ContainerMeta):
class List(list, metaclass=ContainerMeta):

"""Base class for a homogeneous list of attribute converters."""

Expand All @@ -126,7 +126,7 @@ def to_value(cls, obj): # pylint: disable=E0213
if not cls.item_type:
raise NotImplementedError("List subclass must specify item type")

value = []
value = cls.__new__(cls)

for item in cls.to_list(obj):
value.append(cls.item_type.to_value(item))
Expand Down
9 changes: 7 additions & 2 deletions yorm/test/test_container.py
Expand Up @@ -25,6 +25,7 @@ class SampleDictionaryWithInitialization(Dictionary):
"""Sample dictionary container with initialization."""

def __init__(self, var1, var2, var3):
super().__init__()
self.var1 = var1
self.var2 = var2
self.var3 = var3
Expand Down Expand Up @@ -88,9 +89,13 @@ def test_not_implemented(self):

def test_dict_as_object(self):
"""Verify a `Dictionary` can be used as an attribute."""
dictionary = SampleDictionaryWithInitialization(1, 2, 3)
dictionary = SampleDictionaryWithInitialization(1, 2, 3.0)
value = {'var1': 1, 'var2': '2'}
assert value == dictionary.to_value(dictionary)
value2 = dictionary.to_value(dictionary)
assert value == value2
assert 1 == value2.var1
assert '2' == value2.var2
assert not hasattr(value2, 'var3') # lost in conversion


class TestList:
Expand Down

0 comments on commit b2faffd

Please sign in to comment.