Spec URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons.spec SRPM URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons-1.2.0-1.fc32.src.rpm Project URL: https://github.com/ramonhagenaars/jsons Description: Jsons is a library that allows you to serialize your plain old Python objects to readable json (dicts or strings) and deserialize them back. No magic, no special types, no polluting your objects. Koji scratch build: fails due to missing dependency rpmlint output: $ rpmlint python-jsons-1.2.0-1.fc32.src.rpm python-jsons.src: W: spelling-error Summary(en_US) de -> DE, ed, d python-jsons.src: W: spelling-error %description -l en_US json -> son, j son, soon python-jsons.src: W: spelling-error %description -l en_US dicts -> ducts, dicta, dict python-jsons.src: W: spelling-error %description -l en_US deserialize -> serialize, desalinize 1 packages and 0 specfiles checked; 0 errors, 4 warnings. $ rpmlint python3-jsons-1.2.0-1.fc32.noarch.rpm python3-jsons.noarch: W: spelling-error Summary(en_US) de -> DE, ed, d python3-jsons.noarch: W: spelling-error %description -l en_US json -> son, j son, soon python3-jsons.noarch: W: spelling-error %description -l en_US dicts -> ducts, dicta, dict python3-jsons.noarch: W: spelling-error %description -l en_US deserialize -> serialize, desalinize 1 packages and 0 specfiles checked; 0 errors, 4 warnings. Fedora Account System Username: fab
> Koji scratch build: > fails due to missing dependency Yes, the following needs to be added next to the existing BuildRequires: BuildRequires: python3dist(typish) Tested in COPR: https://copr.fedorainfracloud.org/coprs/andymenderunix/metrics2mqtt-and-dependencies/build/1650399/ There is quite a lot of tests failing, however. I'll look into it. =================================== FAILURES =================================== ____________ TestSpecificVersions.test_dump_dataclass_with_optional ____________ args = (<tests.test_specific_versions.TestSpecificVersions testMethod=test_dump_dataclass_with_optional>,) kwargs = {} @skipUnless(dont_skip, reason=reason) def _wrapper(*args, **kwargs): > return decorated(*args, **kwargs) tests/test_specific_versions.py:31: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_specific_versions.py:88: in test_dump_dataclass_with_optional self.assertDictEqual(expected, dumped) E AssertionError: {'x': [42, None, 123]} != {} E - {'x': [42, None, 123]} E + {} ______________ TestSpecificVersions.test_namedtuple_with_optional ______________ args = (<tests.test_specific_versions.TestSpecificVersions testMethod=test_namedtuple_with_optional>,) kwargs = {} @skipUnless(dont_skip, reason=reason) def _wrapper(*args, **kwargs): > return decorated(*args, **kwargs) tests/test_specific_versions.py:31: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_specific_versions.py:74: in test_namedtuple_with_optional jsons.load({'arg': None}, NamedTupleWithOptional)) jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) jsons/_load_impl.py:110: in _do_load result = deserializer(json_obj, cls, **kwargs) jsons/deserializers/default_tuple.py:23: in default_tuple_deserializer return default_namedtuple_deserializer(obj, cls, key_transformer=key_transformer, **kwargs) jsons/deserializers/default_tuple.py:80: in default_namedtuple_deserializer loaded_field = load(field, cls_, key_transformer=key_transformer, **kwargs) jsons/_load_impl.py:75: in load _check_for_none(json_obj, cls) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ json_obj = None, cls = typing.Optional[str] def _check_for_none(json_obj: object, cls: type): # Check if the json_obj is None and whether or not that is fine. if json_obj is None and not can_match_with_none(cls): cls_name = get_class_name(cls).lower() > raise DeserializationError( message='NoneType cannot be deserialized into {}'.format(cls_name), source=json_obj, target=cls) E jsons.exceptions.DeserializationError: NoneType cannot be deserialized into optional jsons/_load_impl.py:213: DeserializationError _________________________ TestUnion.test_load_optional _________________________ self = <tests.test_union.TestUnion testMethod=test_load_optional> def test_load_optional(self): class TestOptionalInt: def __init__(self, value: Optional[int]): self.value = value # This seems fine. > loaded1 = jsons.load({'value': 42}, cls=TestOptionalInt) tests/test_union.py:102: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) jsons/_load_impl.py:110: in _do_load result = deserializer(json_obj, cls, **kwargs) jsons/deserializers/default_object.py:39: in default_object_deserializer constructor_args = _get_constructor_args(obj, cls, **kwargs) jsons/deserializers/default_object.py:63: in _get_constructor_args key, value = _get_value_for_attr(obj=obj, jsons/deserializers/default_object.py:93: in _get_value_for_attr result = sig_key, _get_value_from_obj(obj, cls, sig, sig_key, jsons/deserializers/default_object.py:134: in _get_value_from_obj value = load(obj[sig_key], cls_, meta_hints=new_hints, **kwargs) jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ json_obj = 42, deserializer = None, cls = typing.Optional[int], initial = False kwargs = {'_initial': False, 'attr_getters': None, 'fork_inst': <class 'jsons._common_impl.StateHolder'>, 'meta_hints': {}, ...} cls_name = 'typing.Optional' def _do_load(json_obj: object, deserializer: callable, cls: type, initial: bool, **kwargs): cls_name = get_class_name(cls, fully_qualified=True) if deserializer is None: > raise DeserializationError('No deserializer for type "{}"'.format(cls_name), json_obj, cls) E jsons.exceptions.DeserializationError: No deserializer for type "typing.Optional" jsons/_load_impl.py:108: DeserializationError __________________________ TestUnion.test_load_union ___________________________ self = <tests.test_union.TestUnion testMethod=test_load_union> def test_load_union(self): class A: def __init__(self, x): self.x = x class B: def __init__(self, x: Optional[int]): self.x = x class C: def __init__(self, x: Union[datetime.datetime, A]): self.x = x # Test loading with None value without type hint. self.assertEqual(None, jsons.load({'x': None}, A).x) # Test Optional with a value. > self.assertEqual(1, jsons.load({'x': 1}, B).x) tests/test_union.py:63: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) jsons/_load_impl.py:110: in _do_load result = deserializer(json_obj, cls, **kwargs) jsons/deserializers/default_object.py:39: in default_object_deserializer constructor_args = _get_constructor_args(obj, cls, **kwargs) jsons/deserializers/default_object.py:63: in _get_constructor_args key, value = _get_value_for_attr(obj=obj, jsons/deserializers/default_object.py:93: in _get_value_for_attr result = sig_key, _get_value_from_obj(obj, cls, sig, sig_key, jsons/deserializers/default_object.py:134: in _get_value_from_obj value = load(obj[sig_key], cls_, meta_hints=new_hints, **kwargs) jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ json_obj = 1, deserializer = None, cls = typing.Optional[int], initial = False kwargs = {'_initial': False, 'attr_getters': None, 'fork_inst': <class 'jsons._common_impl.StateHolder'>, 'meta_hints': {}, ...} cls_name = 'typing.Optional' def _do_load(json_obj: object, deserializer: callable, cls: type, initial: bool, **kwargs): cls_name = get_class_name(cls, fully_qualified=True) if deserializer is None: > raise DeserializationError('No deserializer for type "{}"'.format(cls_name), json_obj, cls) E jsons.exceptions.DeserializationError: No deserializer for type "typing.Optional" jsons/_load_impl.py:108: DeserializationError __________________ TestVarious.test_load_recursive_structure ___________________ self = <tests.test_various.TestVarious testMethod=test_load_recursive_structure> def test_load_recursive_structure(self): source = { 'value': 10, 'next': { 'value': 20, 'next': { 'value': 30, 'next': None } } } > loaded = jsons.load(source, Node) tests/test_various.py:53: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) jsons/_load_impl.py:110: in _do_load result = deserializer(json_obj, cls, **kwargs) jsons/deserializers/default_object.py:39: in default_object_deserializer constructor_args = _get_constructor_args(obj, cls, **kwargs) jsons/deserializers/default_object.py:63: in _get_constructor_args key, value = _get_value_for_attr(obj=obj, jsons/deserializers/default_object.py:93: in _get_value_for_attr result = sig_key, _get_value_from_obj(obj, cls, sig, sig_key, jsons/deserializers/default_object.py:134: in _get_value_from_obj value = load(obj[sig_key], cls_, meta_hints=new_hints, **kwargs) jsons/_load_impl.py:98: in load return _do_load(json_obj, deserializer, cls, initial, **kwargs_) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ json_obj = {'next': {'next': None, 'value': 30}, 'value': 20} deserializer = None, cls = typing.Optional[tests.test_various.Node] initial = False kwargs = {'_initial': False, 'attr_getters': None, 'fork_inst': <class 'jsons._common_impl.StateHolder'>, 'meta_hints': {}, ...} cls_name = 'typing.Optional' def _do_load(json_obj: object, deserializer: callable, cls: type, initial: bool, **kwargs): cls_name = get_class_name(cls, fully_qualified=True) if deserializer is None: > raise DeserializationError('No deserializer for type "{}"'.format(cls_name), json_obj, cls) E jsons.exceptions.DeserializationError: No deserializer for type "typing.Optional" jsons/_load_impl.py:108: DeserializationError
I submitted a ticket with upstream: https://github.com/ramonhagenaars/jsons/issues/115
(In reply to Andy Mender from comment #1) > > Koji scratch build: > > fails due to missing dependency > > Yes, the following needs to be added next to the existing BuildRequires: > BuildRequires: python3dist(typish) Added %changelog * Tue Sep 08 2020 Fabian Affolter <mail> - 1.2.0-2 - Add missing BR (rhbz#1875997) Updated files: Spec URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons.spec SRPM URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons-1.2.0-2.fc32.src.rpm
> Added Thumbs up! Honestly, I'm not quite sure how to proceed with this, however. I rebuilt the package in COPR again: https://copr.fedorainfracloud.org/coprs/andymenderunix/metrics2mqtt-and-dependencies/build/1654723/ Have a look at the logs specifically. The reason why the build fails on Fedora 32 is because one of the tests shows lower than expected performance: https://github.com/ramonhagenaars/jsons/blob/master/tests/test_performance.py#L44 Below an example on aarch64. It's a lot worse on s390 (94.922601 seconds) and armhfp (78.928779 seconds). Out of these aarch64, armhfp and x86_64 are relevant. > =================================== FAILURES =================================== > __________________________ TestPerformance.test_dump ___________________________ > self = <tests.test_performance.TestPerformance testMethod=test_dump> > def test_dump(self): > > self._do_test_dump(16) > tests/test_performance.py:45: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > tests/test_performance.py:67: in _do_test_dump > self.assertTrue(delta_sec3 < time_limit, 'The operation took {} seconds'.format(delta_sec3)) > E AssertionError: False is not true : The operation took 16.243726 seconds I'm pretty sure we could argue with upstream to up the number here, since it's arbitrary anyway. Still, the differences in timings are huge. Fedora 33 and Rawhide have bigger problems due to the switch to Python 3.9. Either the test cases need to be revisited or the code they cover. I can have a look over the weekend to maybe file some PRs, but no earlier.
Locally the performance tests are passing but are slowing down the build process with no real value for us. %changelog * Mon Sep 14 2020 Fabian Affolter <mail> - 1.2.0-3 - Make performance tests optional Updated files: Spec URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons.spec SRPM URL: https://fab.fedorapeople.org/packages/SRPMS/python-jsons-1.2.0-3.fc32.src.rpm
> Locally the performance tests are passing but are slowing down the build process with no real value for us. > > %changelog > * Mon Sep 14 2020 Fabian Affolter <mail> - 1.2.0-3 > - Make performance tests optional Yup, these can be optional. Good idea! Since there is still no news from upstream on the ticket I opened, I'll try to work on a patch in the following days.
Quick update, unfortunately, I couldn't find a fix. It seems the tests for python-jsons are running into some corner cases in the 'typing' library. The Python docs don't mention any changes in Python 3.9 so it's hard to tell why the tests could be failing. Might as well be a bug in the 'typing' library.
Could we go on with the excluded performance tests?
> Could we go on with the excluded performance tests? I don't think that's a good idea. The performance tests can be disabled, yes. However, the remaining tests touch on key functionalities of the "python-jsons" library and fail on Python 3.8 and Python 3.9. I received a response to my ticket with upstream a while back so please have a look whether the most recent release builds cleanly on Rawhide (and optionally F33 if you would like to cover that release, too).
Good news! I tested the most recent release in COPR and the issues with Python 3.8 and 3.9, and python-typish have been resolved! https://copr.fedorainfracloud.org/coprs/andymenderunix/python-iot/build/1769669/ You can go ahead, update to version 1.3.0 (https://github.com/ramonhagenaars/jsons/releases/tag/v1.3.0) and disable the performance test "TestPerformance.test_dump". Package approved!
I see the repo request was not submitted yet. Need any help? :)
I think this can be pushed already, since the issues were squared away. Any help needed?
(fedscm-admin): The Pagure repository was created at https://src.fedoraproject.org/rpms/python-jsons
FEDORA-2020-1a3b7045f0 has been submitted as an update to Fedora 33. https://bodhi.fedoraproject.org/updates/FEDORA-2020-1a3b7045f0
FEDORA-2020-1a3b7045f0 has been pushed to the Fedora 33 testing repository. In short time you'll be able to install the update with the following command: `sudo dnf install --enablerepo=updates-testing --advisory=FEDORA-2020-1a3b7045f0 \*` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2020-1a3b7045f0 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2020-1a3b7045f0 has been pushed to the Fedora 33 stable repository. If problem still persists, please make note of it in this bug report.