Skip to content

Commit

Permalink
Categories now only allow strings as keys, numbers, strings, bools as…
Browse files Browse the repository at this point in the history
… values

This had been stated in the docs but hadn't yet been codified in the way
categories actually worked. This has been changed. Tests added to check
the behavior works as stated.

Setting the value for a category to ``None`` results in no change.
  • Loading branch information
dotsdl committed Mar 17, 2016
1 parent 1b5a4c4 commit de13b43
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 13 deletions.
35 changes: 22 additions & 13 deletions src/datreant/core/limbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,37 +356,46 @@ def _dict(self):
def add(self, *categorydicts, **categories):
"""Add any number of categories to the Treant.
Categories are key-value pairs of strings that serve to differentiate
Treants from one another. Sometimes preferable to tags.
Categories are key-value pairs that serve to differentiate Treants from
one another. Sometimes preferable to tags.
If a given category already exists (same key), the value given will
replace the value for that category.
:Keywords:
*categorydict*
dict of categories to add; keys used as keys, values used as
values. Both keys and values must be convertible to strings
using the str() builtin.
*categories*
Categories to add. Keyword used as key, value used as value.
Both must be convertible to strings using the str() builtin.
Keys must be strings.
Values may be ints, floats, strings, or bools. ``None`` as a value
will not the existing value for the key, if present.
Parameters
----------
categorydict : dict
Dict of categories to add; keys used as keys, values used as
values.
categories : dict
Categories to add. Keyword used as key, value used as value.
"""
outcats = dict()
for categorydict in categorydicts:
if isinstance(categorydict, dict):
outcats.update(categorydict)
else:
raise TypeError("Invalid arguments; non-keyword" +
raise TypeError("Invalid arguments; non-keyword"
" arguments must be dicts")

outcats.update(categories)

with self._treant._write:
for key, value in outcats.items():
if (isinstance(value, (int, float, string_types, bool)) or
value is None):
if not isinstance(key, string_types):
raise TypeError("Keys must be strings.")

if (isinstance(value, (int, float, string_types, bool))):
self._treant._state['categories'][key] = value
elif value is not None:
raise TypeError("Values must be ints, floats,"
" strings, or bools.")

def remove(self, *categories):
"""Remove categories from Treant.
Expand Down
32 changes: 32 additions & 0 deletions src/datreant/core/tests/test_treants.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,38 @@ def test_add_wrong(self, treant):
with pytest.raises(TypeError):
treant.categories.add(['mark', 'matt'])

def test_add_wrong_keys(self, treant):
with pytest.raises(TypeError):
treant.categories[2] = 'twenty'

with pytest.raises(TypeError):
treant.categories[['blarg']] = "nothin'"

with pytest.raises(TypeError):
treant.categories[None] = "literally nothin'"

with pytest.raises(TypeError):
treant.categories[True] = "tautologically"

def test_add_wrong_values(self, treant):
with pytest.raises(TypeError):
treant.categories['bark'] = ['shaggy']

with pytest.raises(TypeError):
treant.categories['snark'] = {'yes'}

def test_None_no_change(self, treant):
"""Setting a category to ``None`` should not change the value.
"""
treant.categories['bark'] = 'smooth'
treant.categories['bark'] = None

assert treant.categories['bark'] == 'smooth'

treant.categories.add(bark=None)

assert treant.categories['bark'] == 'smooth'

def test_KeyError(self, treant):
with pytest.raises(KeyError):
treant.categories['hello?']
Expand Down

0 comments on commit de13b43

Please sign in to comment.