mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 10:16:11 +00:00
Clean json returned from server for keys with None values
Add testing
This commit is contained in:
parent
8a3ca73d52
commit
ed96dc8ad5
7 changed files with 188 additions and 4 deletions
66
.gitignore
vendored
66
.gitignore
vendored
|
@ -1,12 +1,72 @@
|
||||||
*.pyo
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__local__/
|
__local__/
|
||||||
machine_guid
|
machine_guid
|
||||||
/resources/media/Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode/
|
.vscode/
|
||||||
pyinstrument/
|
pyinstrument/
|
||||||
pyinstrument_cext.so
|
|
||||||
|
# Now managed by templates
|
||||||
addon.xml
|
addon.xml
|
||||||
|
|
||||||
|
*.log
|
||||||
|
|
|
@ -11,6 +11,7 @@ from six import string_types, ensure_str
|
||||||
from helper.utils import JsonDebugPrinter
|
from helper.utils import JsonDebugPrinter
|
||||||
from helper import LazyLogger
|
from helper import LazyLogger
|
||||||
from helper.exceptions import HTTPException
|
from helper.exceptions import HTTPException
|
||||||
|
from jellyfin.utils import clean_none_dict_values
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ class HTTP(object):
|
||||||
LOG.debug("---<[ http ][%s ms]", elapsed)
|
LOG.debug("---<[ http ][%s ms]", elapsed)
|
||||||
LOG.debug(JsonDebugPrinter(response))
|
LOG.debug(JsonDebugPrinter(response))
|
||||||
|
|
||||||
return response
|
return clean_none_dict_values(response)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
43
jellyfin_kodi/jellyfin/utils.py
Normal file
43
jellyfin_kodi/jellyfin/utils.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
from six import string_types
|
||||||
|
from six.moves import collections_abc
|
||||||
|
|
||||||
|
|
||||||
|
def clean_none_dict_values(obj):
|
||||||
|
"""
|
||||||
|
Recursively remove keys with a value of None
|
||||||
|
"""
|
||||||
|
if not isinstance(obj, collections_abc.Iterable) or isinstance(obj, string_types):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
queue = [obj]
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
item = queue.pop()
|
||||||
|
|
||||||
|
if isinstance(item, collections_abc.Mapping):
|
||||||
|
mutable = isinstance(item, collections_abc.MutableMapping)
|
||||||
|
remove = []
|
||||||
|
|
||||||
|
for key, value in item.items():
|
||||||
|
if value is None and mutable:
|
||||||
|
remove.append(key)
|
||||||
|
|
||||||
|
elif isinstance(value, string_types):
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif isinstance(value, collections_abc.Iterable):
|
||||||
|
queue.append(value)
|
||||||
|
|
||||||
|
if mutable:
|
||||||
|
# Remove keys with None value
|
||||||
|
for key in remove:
|
||||||
|
item.pop(key)
|
||||||
|
|
||||||
|
elif isinstance(item, collections_abc.Iterable):
|
||||||
|
for value in item:
|
||||||
|
if value is None or isinstance(value, string_types):
|
||||||
|
continue
|
||||||
|
elif isinstance(value, collections_abc.Iterable):
|
||||||
|
queue.append(value)
|
||||||
|
|
||||||
|
return obj
|
13
requirements-dev.txt
Normal file
13
requirements-dev.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
setuptools >= 44.1.1 # Old setuptools causes script.module.addon.signals to fail installing
|
||||||
|
six >= 1.13
|
||||||
|
python-dateutil >= 2.8.1
|
||||||
|
requests >= 2.22
|
||||||
|
futures >= 2.2; python_version < '3.0'
|
||||||
|
git+https://github.com/oddstr13/Kodistubs@python3 # Kodistubs >= 18
|
||||||
|
git+https://github.com/romanvm/kodi.six
|
||||||
|
git+https://github.com/ruuk/script.module.addon.signals
|
||||||
|
|
||||||
|
pytest >= 4.6.11
|
||||||
|
coverage >= 5.2
|
||||||
|
flake8 >= 3.8
|
||||||
|
flake8-import-order >= 0.18
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
51
tests/test_clean_none_dict_values.py
Normal file
51
tests/test_clean_none_dict_values.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
sys.path.insert(0, 'jellyfin_kodi')
|
||||||
|
|
||||||
|
from jellyfin.utils import clean_none_dict_values # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("obj,expected", [
|
||||||
|
(None, None),
|
||||||
|
([None, 1, 2, 3, None, 4], [None, 1, 2, 3, None, 4]),
|
||||||
|
({'foo': None, 'bar': 123}, {'bar': 123}),
|
||||||
|
({
|
||||||
|
'dict': {
|
||||||
|
'empty': None,
|
||||||
|
'string': "Hello, Woorld!",
|
||||||
|
},
|
||||||
|
'number': 123,
|
||||||
|
'list': [
|
||||||
|
None,
|
||||||
|
123,
|
||||||
|
"foo",
|
||||||
|
{
|
||||||
|
'empty': None,
|
||||||
|
'number': 123,
|
||||||
|
'string': "foo",
|
||||||
|
'list': [],
|
||||||
|
'dict': {},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
'dict': {
|
||||||
|
'string': "Hello, Woorld!",
|
||||||
|
},
|
||||||
|
'number': 123,
|
||||||
|
'list': [
|
||||||
|
None,
|
||||||
|
123,
|
||||||
|
"foo",
|
||||||
|
{
|
||||||
|
'number': 123,
|
||||||
|
'string': "foo",
|
||||||
|
'list': [],
|
||||||
|
'dict': {},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
def test_clean_none_dict_values(obj, expected):
|
||||||
|
assert clean_none_dict_values(obj) == expected
|
16
tox.ini
16
tox.ini
|
@ -6,3 +6,19 @@ extend-ignore =
|
||||||
I202
|
I202
|
||||||
per-file-ignores =
|
per-file-ignores =
|
||||||
*/__init__.py: F401
|
*/__init__.py: F401
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
minversion = 4.6
|
||||||
|
testpaths =
|
||||||
|
tests
|
||||||
|
|
||||||
|
[coverage:run]
|
||||||
|
source =
|
||||||
|
jellyfin_kodi
|
||||||
|
context.py
|
||||||
|
context_play.py
|
||||||
|
default.py
|
||||||
|
service.py
|
||||||
|
.config/generate_xml.py
|
||||||
|
omit = tests/*
|
||||||
|
command_line = -m pytest
|
||||||
|
|
Loading…
Reference in a new issue