Skip to content

Commit

Permalink
Merge pull request #106 from paulocheque/lookup_fix
Browse files Browse the repository at this point in the history
[fix] Lookup alias fix
  • Loading branch information
paulocheque committed Jan 4, 2020
2 parents dcdf068 + 3c442ce commit fc63745
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 11 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ compile:
env/bin/python -OO -m compileall .

test:
clear ; env/bin/pytest --create-db --reuse-db --no-migrations
# Run specific test:
# ARGS=pytest django_dynamic_fixture.tests.FILE::CLASS::METHOD make test
clear ; env/bin/pytest --create-db --reuse-db --no-migrations ${ARGS}
# clear ; time env/bin/tox --parallel all -e django111-py27
# clear ; time env/bin/tox --parallel all -e django20-py37

Expand Down
42 changes: 32 additions & 10 deletions django_dynamic_fixture/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,43 @@

LOOKUP_SEP = '__'

def look_up_alias(**kwargs):
def look_up_alias(ddf_as_f=True, **kwargs):
"""
a__b__c=1 => a=F(b=F(c=1))
Example of parameters:
a__b__c=1 => {a: {b: {c: 1}}}
"""
field_dict = {}
for key, value in kwargs.items():
parts = key.split(LOOKUP_SEP)
current_dict = {parts[-1]: value}
first_fields = parts[:-1]
first_fields.reverse()
for part in first_fields:
current_dict = {part: F(**current_dict)}
field_dict.update(current_dict)
for alias, value in kwargs.items():
parts = alias.split(LOOKUP_SEP)
level_dict = field_dict
for part in parts[:-1]:
level_dict = level_dict.setdefault(part, {})
level_dict[parts[-1]] = value
if ddf_as_f:
for root, value in field_dict.items():
field_dict[root] = dict_to_f(value)
return field_dict


def dict_to_f(value):
"""
Example:
1 => 1
{b: 1 => F(b=1)
{b: {c: 1}} => F(b=F(c=1))
"""
if not isinstance(value, dict):
return value
else:
kwargs = {}
for k, v in value.items():
if not isinstance(v, dict):
kwargs[k] = v
else:
kwargs[k] = dict_to_f(v)
return F(**kwargs)


def fixture(**kwargs):
"""
DynamicFixture factory: It instantiate a DynamicFixture using global configurations.
Expand Down Expand Up @@ -184,3 +205,4 @@ def teach(model: typing.Type[INSTANCE_TYPE], lesson=None, **kwargs):
exec(hack_to_avoid_py2_syntax_errors)
except (ImportError, SyntaxError) as e:
pass

42 changes: 42 additions & 0 deletions django_dynamic_fixture/tests/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ def test_full_example(self):
assert instance.manytomany.all()[1].integer == 1005
assert instance.manytomany.all()[2].selfforeignkey.integer == 1006

def test_two_properties_same_object(self):
instance = G(ModelWithRelationships, integer=1000, foreignkey=F(integer=1001, integer_b=1002))
assert instance.integer == 1000
assert instance.foreignkey.integer == 1001
assert instance.foreignkey.integer_b == 1002

def test_using_look_up_alias(self):
instance = G(ModelWithRelationships, integer=1000,
foreignkey__integer=1001,
Expand All @@ -88,6 +94,22 @@ def test_using_look_up_alias(self):
assert instance.manytomany.all()[1].integer == 1005
assert instance.manytomany.all()[2].selfforeignkey.integer == 1006

def test_using_look_up_alias_two_properties_same_object(self):
instance = G(ModelWithRelationships, integer=1000,
foreignkey__integer=1001,
foreignkey__integer_b=1002)
assert instance.integer == 1000
assert instance.foreignkey.integer == 1001
assert instance.foreignkey.integer_b == 1002

def test_using_look_up_alias_two_properties_same_object(self):
instance = G(ModelWithRelationships, integer=1000,
foreignkey__integer=1001,
foreignkey__integer_b=1002)
assert instance.integer == 1000
assert instance.foreignkey.integer_b == 1002
assert instance.foreignkey.integer == 1001


class CShortcutTest(TestCase):
def test_copying_from_the_same_model(self):
Expand Down Expand Up @@ -146,6 +168,26 @@ def test_get(self):


class LookUpSeparatorTest(TestCase):
def test_look_up_alias_with_all_params_combination(self):
assert {'a': 1} == look_up_alias(a=1, ddf_as_f=False)
assert {'a': 1, 'b': 2} == look_up_alias(a=1, b=2, ddf_as_f=False)
assert {'a': {'b': 1}} == look_up_alias(a__b=1, ddf_as_f=False)
assert {'a': {'b': 1}, 'c': 2} == look_up_alias(a__b=1, c=2, ddf_as_f=False)
assert {'a': {'b': 1}, 'c': {'d': 2}} == look_up_alias(a__b=1, c__d=2, ddf_as_f=False)
assert {'a': {'b': 1, 'c': 2}} == look_up_alias(a__b=1, a__c=2, ddf_as_f=False)
assert {'a': {'b': 1, 'c': {'d': 2}}} == look_up_alias(a__b=1, a__c__d=2, ddf_as_f=False)
assert {'a': {'b': 1, 'c': {'d': 2}}, 'e': {'f': 3}, 'g': 4} == look_up_alias(a__b=1, a__c__d=2, e__f=3, g=4, ddf_as_f=False)

def test_look_up_alias_as_f_with_all_params_combination(self):
assert {'a': 1} == look_up_alias(a=1)
assert {'a': 1, 'b': 2} == look_up_alias(a=1, b=2)
assert {'a': F(b=1)} == look_up_alias(a__b=1)
assert {'a': F(b=1), 'c': 2} == look_up_alias(a__b=1, c=2)
assert {'a': F(b=1), 'c': F(d=2)} == look_up_alias(a__b=1, c__d=2)
assert {'a': F(b=1, c=2)} == look_up_alias(a__b=1, a__c=2)
assert {'a': F(b=1, c=F(d=2))} == look_up_alias(a__b=1, a__c__d=2)
assert {'a': F(b=1, c=F(d=2)), 'e': F(f=3), 'g': 4} == look_up_alias(a__b=1, a__c__d=2, e__f=3, g=4)

def test_look_up_alias_with_just_one_parameter(self):
assert {'a': 1} == look_up_alias(a=1)
assert {'a': F()} == look_up_alias(a=F())
Expand Down

0 comments on commit fc63745

Please sign in to comment.