mirror of
https://github.com/JockeTF/fimfarchive.git
synced 2024-11-22 05:17:59 +01:00
Add walker for JSON objects
This commit is contained in:
parent
8e8dac864a
commit
aa6cafa305
2 changed files with 110 additions and 3 deletions
|
@ -27,7 +27,7 @@ import os
|
|||
import shutil
|
||||
from functools import partial
|
||||
from importlib_resources import read_binary, read_text
|
||||
from typing import Any, Dict, Optional, Type, TypeVar, Union
|
||||
from typing import Any, Dict, Iterator, Optional, Type, TypeVar, Union
|
||||
|
||||
from tqdm import tqdm
|
||||
|
||||
|
@ -124,6 +124,42 @@ class PersistedDict(Dict[str, Any]):
|
|||
os.remove(self.temp)
|
||||
|
||||
|
||||
class JayWalker:
|
||||
"""
|
||||
Walker for JSON objects.
|
||||
"""
|
||||
|
||||
def walk(self, data) -> None:
|
||||
"""
|
||||
Walks the attributes of a JSON object.
|
||||
|
||||
Args:
|
||||
data: The object to walk.
|
||||
"""
|
||||
iterator: Iterator
|
||||
|
||||
if isinstance(data, dict):
|
||||
iterator = iter(data.items())
|
||||
elif isinstance(data, list):
|
||||
iterator = enumerate(data)
|
||||
else:
|
||||
return
|
||||
|
||||
for key, value in iterator:
|
||||
self.handle(data, key, value)
|
||||
|
||||
def handle(self, data, key, value) -> None:
|
||||
"""
|
||||
Handles a single JSON entry.
|
||||
|
||||
Args:
|
||||
data: The current object.
|
||||
key: The key of the entry.
|
||||
value: The value of the entry.
|
||||
"""
|
||||
self.walk(value)
|
||||
|
||||
|
||||
def find_flavor(story: Story, flavor: Type[F]) -> Optional[F]:
|
||||
"""
|
||||
Searches for a flavor of a specific type.
|
||||
|
|
|
@ -24,11 +24,12 @@ Utility tests.
|
|||
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from fimfarchive.flavors import DataFormat, MetaFormat, MetaPurity
|
||||
from fimfarchive.utils import find_flavor, Empty, PersistedDict
|
||||
from fimfarchive.utils import find_flavor, Empty, JayWalker, PersistedDict
|
||||
|
||||
|
||||
class TestEmpty:
|
||||
|
@ -134,7 +135,7 @@ class TestPersistedDict:
|
|||
"""
|
||||
Tests data is replaced on load.
|
||||
"""
|
||||
extra = {object(): object()}
|
||||
extra = {'key': object()}
|
||||
data = PersistedDict(tmpfile)
|
||||
data.update(extra)
|
||||
data.load()
|
||||
|
@ -192,6 +193,76 @@ class TestPersistedDict:
|
|||
assert dict(data) == sample
|
||||
|
||||
|
||||
class TestJayWalker:
|
||||
"""
|
||||
JayWalker tests.
|
||||
"""
|
||||
|
||||
@pytest.fixture
|
||||
def walker(self):
|
||||
"""
|
||||
Returns a walker instance.
|
||||
"""
|
||||
walker = JayWalker()
|
||||
|
||||
with patch.object(walker, 'handle', wraps=walker.handle):
|
||||
yield walker
|
||||
|
||||
@pytest.mark.parametrize('obj', [None, 'alpaca', 42])
|
||||
def test_ignored_walk(self, walker, obj):
|
||||
"""
|
||||
Tests walker ignores plain values.
|
||||
"""
|
||||
walker.walk(obj)
|
||||
walker.handle.assert_not_called()
|
||||
|
||||
def test_list_walk(self, walker):
|
||||
"""
|
||||
Tests walker can walk lists.
|
||||
"""
|
||||
data = ['a', 'b', 'c']
|
||||
walker.walk(data)
|
||||
|
||||
assert walker.handle.mock_calls == [
|
||||
call(data, 0, 'a'),
|
||||
call(data, 1, 'b'),
|
||||
call(data, 2, 'c'),
|
||||
]
|
||||
|
||||
def test_dict_walk(self, walker):
|
||||
"""
|
||||
Tests walker can walk dicts.
|
||||
"""
|
||||
data = {0: 'a', 1: 'b', 2: 'c'}
|
||||
walker.walk(data)
|
||||
|
||||
assert walker.handle.mock_calls == [
|
||||
call(data, 0, 'a'),
|
||||
call(data, 1, 'b'),
|
||||
call(data, 2, 'c'),
|
||||
]
|
||||
|
||||
def test_nested_walk(self, walker):
|
||||
"""
|
||||
Tests walker can walk nested objects.
|
||||
"""
|
||||
data = {
|
||||
'a': ['b', 'c'],
|
||||
'd': {'e': 'f'},
|
||||
}
|
||||
|
||||
walker.walk([data])
|
||||
|
||||
assert walker.handle.mock_calls == [
|
||||
call([data], 0, data),
|
||||
call(data, 'a', data['a']),
|
||||
call(data['a'], 0, 'b'),
|
||||
call(data['a'], 1, 'c'),
|
||||
call(data, 'd', data['d']),
|
||||
call(data['d'], 'e', 'f'),
|
||||
]
|
||||
|
||||
|
||||
class TestFindFlavor:
|
||||
"""
|
||||
find_flavor tests.
|
||||
|
|
Loading…
Reference in a new issue