Skip to content

Commit

Permalink
Merge pull request #15 from Toilal/to_dict_refactoring
Browse files Browse the repository at this point in the history
Refactor Matches to_dict() method for better API
  • Loading branch information
Toilal committed May 31, 2017
2 parents 375fcb4 + 4fbd124 commit 8738849
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 12 deletions.
8 changes: 5 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ repetition on chain part.
... .regex(r'v(?P<version>\d+)').repeater('?')\
... .regex(r'[ex-](?P<episode>\d{1,4})').repeater('*')\
... .close() # .repeater(1) could be omitted as it's the default behavior
>>> r.matches("This is E14v2-15-16-17").to_dict(implicit=True) # converts matches to dict and keep multiple values
>>> r.matches("This is E14v2-15-16-17").to_dict() # converts matches to dict
MatchesDict([('episode', [14, 15, 16, 17]), ('version', 2)])
Patterns parameters
Expand Down Expand Up @@ -424,17 +424,19 @@ It has the following additional methods and properties on it.

Retrieves a sequence of all ``Match.tags`` properties.

- ``to_dict(details=False, implicit=False)``
- ``to_dict(details=False, first_value=False, enforce_list=False)``

Convert to an ordered dict, with ``Match.name`` as key and ``Match.value`` as value.

It's a subclass of `OrderedDict`_, that contains a ``matches`` property which is a dict with ``Match.name`` as key
and list of ``Match`` objects as value.

If ``implicit`` is ``True`` and distinct values are found for the same name, value will be converted as list.
If ``first_value`` is ``True`` and distinct values are found for the same name, value will be wrapped to a list.
If ``False``, first value only will be kept and values lists can be retrieved with ``values_list`` which is a dict
with ``Match.name`` as key and list of ``Match.value`` as value.

if ``enforce_list`` is ``True``, all values will be wrapped to a list, even if a single value is found.

If ``details`` is True, ``Match.value`` objects are replaced with complete ``Match`` object.

- ``markers``
Expand Down
20 changes: 13 additions & 7 deletions rebulk/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,25 +493,28 @@ def tags(self):
"""
return self._tag_dict.keys()

def to_dict(self, details=False, implicit=False):
def to_dict(self, details=False, first_value=False, enforce_list=False):
"""
Converts matches to a dict object.
:param details if True, values will be complete Match object, else it will be only string Match.value property
:type details: bool
:param implicit if True, multiple values will be set as a list in the dict. Else, only the first value
will be kept.
:type implicit: bool
:param first_value if True, only the first value will be kept. Else, multiple values will be set as a list in
the dict.
:type first_value: bool
:param enforce_list: if True, value is wrapped in a list even when a single value is found. Else, list values
are available under `values_list` property of the returned dict object.
:type enforce_list: bool
:return:
:rtype: dict
"""
ret = MatchesDict()
for match in sorted(self):
value = match if details else match.value
ret.matches[match.name].append(match)
if value not in ret.values_list[match.name]:
if not enforce_list and value not in ret.values_list[match.name]:
ret.values_list[match.name].append(value)
if match.name in ret.keys():
if implicit:
if not first_value:
if not isinstance(ret[match.name], list):
if ret[match.name] == value:
continue
Expand All @@ -521,7 +524,10 @@ def to_dict(self, details=False, implicit=False):
continue
ret[match.name].append(value)
else:
ret[match.name] = value
if enforce_list and not isinstance(value, list):
ret[match.name] = [value]
else:
ret[match.name] = value
return ret

if six.PY2: # pragma: no cover
Expand Down
7 changes: 5 additions & 2 deletions rebulk/test/test_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,15 +419,18 @@ def test_to_dict(self):
matches.extend(RePattern("Three", name="3bis", tags=["Three", "re"]).matches(input_string))
matches.extend(RePattern(r"(\w+)", name="words").matches(input_string))

kvalues = matches.to_dict()
kvalues = matches.to_dict(first_value=True)
assert kvalues == {"1": "One",
"2": "Two",
"3": "Three",
"3bis": "Three",
"words": "One"}
assert kvalues.values_list["words"] == ["One", "Two", "Three"]

kvalues = matches.to_dict(details=True, implicit=True)
kvalues = matches.to_dict(enforce_list=True)
assert kvalues["words"] == ["One", "Two", "Three"]

kvalues = matches.to_dict(details=True)
assert kvalues["1"].value == "One"

assert len(kvalues["2"]) == 2
Expand Down

0 comments on commit 8738849

Please sign in to comment.