Skip to content

Commit

Permalink
issue-91: Fix munchify for tuples of lists (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
d1618033 committed Feb 5, 2023
1 parent 28c1256 commit ac45751
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
14 changes: 9 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
# Install the testing dependencies from setup.cfg, including pylint
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Upgrade pip
run: python -m pip install --upgrade pip
- name: Upgrade build tools
- name: Upgrade build tools and pytest
run: pip install --upgrade build wheel setuptools
- run: pip install .[testing]
- run: pylint munch setup.py tests
- name: Install dependencies
run: pip install ".[testing,yaml]"
- name: Lint
run: pylint munch setup.py tests
13 changes: 9 additions & 4 deletions munch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,21 @@ def munchify(x, factory=Munch):
seen = dict()

def munchify_cycles(obj):
partial, already_seen = pre_munchify_cycles(obj)
if already_seen:
return partial
return post_munchify(partial, obj)

def pre_munchify_cycles(obj):
# If we've already begun munchifying obj, just return the already-created munchified obj
try:
return seen[id(obj)]
return seen[id(obj)], True
except KeyError:
pass

# Otherwise, first partly munchify obj (but without descending into any lists or dicts) and save that
seen[id(obj)] = partial = pre_munchify(obj)
# Then finish munchifying lists and dicts inside obj (reusing munchified obj if cycles are encountered)
return post_munchify(partial, obj)
return partial, False

def pre_munchify(obj):
# Here we return a skeleton of munchified obj, which is enough to save for later (in case
Expand All @@ -462,7 +467,7 @@ def pre_munchify(obj):
return type(obj)()
elif isinstance(obj, tuple):
type_factory = getattr(obj, "_make", type(obj))
return type_factory(munchify_cycles(item) for item in obj)
return type_factory(pre_munchify_cycles(item)[0] for item in obj)
else:
return obj

Expand Down
14 changes: 14 additions & 0 deletions tests/test_munch.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,17 @@ def test_get_default_value(munch_obj):
munch_cls = type(munch_obj)
kwargs = {} if munch_cls != DefaultFactoryMunch else {"default_factory": munch_obj.default_factory}
munch_cls.fromDict(data, **kwargs)


def test_munchify_tuple_list():
data = ([{'A': 'B'}],)
actual = munchify(data)
expected = ([Munch(A='B')],)
assert actual == expected


def test_munchify_tuple_list_more_elements():
data = (1, 2, [{'A': 'B'}])
actual = munchify(data)
expected = (1, 2, [Munch({'A': 'B'})])
assert actual == expected

0 comments on commit ac45751

Please sign in to comment.