Skip to content

Commit

Permalink
Fill nested views with flat dictionary
Browse files Browse the repository at this point in the history
  • Loading branch information
Milan Falešník committed Aug 8, 2017
1 parent b31a2b0 commit 62f0cb5
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
45 changes: 45 additions & 0 deletions src/widgetastic/utils.py
Expand Up @@ -477,3 +477,48 @@ def nested_getattr(o, steps):
for step in steps:
result = getattr(result, step)
return result


def deflatten_dict(d):
"""Expands nested dictionary from dot-separated string keys.
Useful when one needs filling a nested view, this can reduce the visual nesting
Turns this:
.. code-block:: python
{'a.b': 1}
Into this:
.. code-block:: python
{'a': {'b': 1}}
The conversion recursively follows dictionaries as values.
Args:
d: Dictionary
Returns:
A dictionary.
"""
current_dict = {}
for key, value in six.iteritems(d):
if not isinstance(key, six.string_types):
current_dict[key] = value
continue
local_dict = current_dict
if isinstance(key, tuple):
attrs = list(key)
else:
attrs = [x.strip() for x in key.split('.')]
dict_lookup = attrs[:-1]
attr_set = attrs[-1]
for attr_name in dict_lookup:
if attr_name not in local_dict:
local_dict[attr_name] = {}
local_dict = local_dict[attr_name]
local_dict[attr_set] = deflatten_dict(value) if isinstance(value, dict) else value
return current_dict
3 changes: 2 additions & 1 deletion src/widgetastic/widget.py
Expand Up @@ -24,7 +24,7 @@
create_item_logger)
from .utils import (
Widgetable, Fillable, ParametrizedLocator, ConstructorResolvable, attributize_string,
normalize_space, nested_getattr)
normalize_space, nested_getattr, deflatten_dict)
from .xpath import quote


Expand Down Expand Up @@ -681,6 +681,7 @@ def fill(self, values):
Returns:
:py:class:`bool` if the fill changed any value.
"""
values = deflatten_dict(values)
was_change = False
self.before_fill(values)
extra_keys = set(values.keys()) - set(self.widget_names)
Expand Down
33 changes: 33 additions & 0 deletions testing/test_basic_widgets.py
Expand Up @@ -88,6 +88,39 @@ class Nested2(View):
assert form.Nested1.Nested2.input2.locatable_parent is None


def test_nested_views_read_fill_flat(browser):
class TestForm(View):
h3 = Text('.//h3')

class Nested1(View):
input1 = TextInput(name='input1')

class Nested2(View):
input2 = Checkbox(id='input2')

form = TestForm(browser)
assert isinstance(form, TestForm)
data = form.read()

assert data['h3'] == 'test test'
assert data['Nested1']['input1'] == ''
assert not data['Nested1']['Nested2']['input2']

assert form.fill({
'Nested1.input1': 'foobar',
'Nested1.Nested2.input2': True,
})

assert form.Nested1.input1.read() == 'foobar'
assert form.Nested1.Nested2.input2.read()

assert form.Nested1.Nested2.input2.hierarchy == [
form, form.Nested1, form.Nested1.Nested2, form.Nested1.Nested2.input2]
assert form.hierarchy == [form]

assert form.Nested1.Nested2.input2.locatable_parent is None


def test_table(browser):
class TestForm(View):
table = Table('#with-thead')
Expand Down

0 comments on commit 62f0cb5

Please sign in to comment.