py-serializable 2.0.0__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {py_serializable-2.0.0 → py_serializable-2.1.0}/CHANGELOG.md +24 -105
  2. {py_serializable-2.0.0 → py_serializable-2.1.0}/PKG-INFO +1 -1
  3. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/conf.py +1 -1
  4. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/__init__.py +46 -13
  5. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/formatters.py +0 -2
  6. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/helpers.py +0 -2
  7. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/json.py +0 -2
  8. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/xml.py +0 -2
  9. {py_serializable-2.0.0 → py_serializable-2.1.0}/pyproject.toml +3 -2
  10. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/__init__.py +0 -2
  11. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/base.py +1 -3
  12. py_serializable-2.1.0/tests/fixtures/the-phoenix-project-defaultNS-isset.SNAPSHOT.xml +1 -0
  13. py_serializable-2.1.0/tests/fixtures/the-phoenix-project-defaultNS-unset.SNAPSHOT.xml +1 -0
  14. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_ignored_attributes.xml +54 -0
  15. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_ignored_elements.xml +59 -0
  16. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_ignored_properties.json +66 -0
  17. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_unignored_attributes.xml +52 -0
  18. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_unignored_elements.xml +56 -0
  19. py_serializable-2.1.0/tests/fixtures/the-phoenix-project_unknown_unignored_properties.json +65 -0
  20. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/model.py +10 -5
  21. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_formatters.py +0 -2
  22. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_helpers.py +24 -2
  23. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_json.py +45 -18
  24. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_oml.py +0 -2
  25. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_oml_serializable_property.py +0 -2
  26. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/test_xml.py +48 -11
  27. py_serializable-2.0.0/tests/fixtures/the-phoenix-project-defaultNS-isset.SNAPSHOT.xml +0 -1
  28. py_serializable-2.0.0/tests/fixtures/the-phoenix-project-defaultNS-unset.SNAPSHOT.xml +0 -1
  29. {py_serializable-2.0.0 → py_serializable-2.1.0}/LICENSE +0 -0
  30. {py_serializable-2.0.0 → py_serializable-2.1.0}/README.md +0 -0
  31. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/Makefile +0 -0
  32. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/changelog.rst +0 -0
  33. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/customising-structure.rst +0 -0
  34. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/examples.rst +0 -0
  35. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/formatters.rst +0 -0
  36. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/getting-started.rst +0 -0
  37. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/index.rst +0 -0
  38. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/make.bat +0 -0
  39. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/migration.rst +0 -0
  40. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/requirements.txt +0 -0
  41. {py_serializable-2.0.0 → py_serializable-2.1.0}/docs/support.rst +0 -0
  42. {py_serializable-2.0.0 → py_serializable-2.1.0}/py_serializable/py.typed +0 -0
  43. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-bookedition-none.json +0 -0
  44. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-bookedition-none.xml +0 -0
  45. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-1-v1.xml +0 -0
  46. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-1-v2.xml +0 -0
  47. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-1-v3.xml +0 -0
  48. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-1-v4.xml +0 -0
  49. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-1.xml +0 -0
  50. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-references.json +0 -0
  51. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-v2.json +0 -0
  52. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-v3.json +0 -0
  53. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-v4.json +0 -0
  54. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-with-ignored.json +0 -0
  55. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case-with-ignored.xml +0 -0
  56. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-camel-case.json +0 -0
  57. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-defaultNS-isset-v4.xml +0 -0
  58. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-defaultNS-mixed-v4.xml +0 -0
  59. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-defaultNS-unset-v4.xml +0 -0
  60. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-kebab-case-1-v2.xml +0 -0
  61. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-kebab-case-1.xml +0 -0
  62. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-kebab-case.json +0 -0
  63. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-snake-case-1.xml +0 -0
  64. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project-snake-case.json +0 -0
  65. {py_serializable-2.0.0 → py_serializable-2.1.0}/tests/fixtures/the-phoenix-project_unnormalized-input_v4.xml +0 -0
@@ -1,131 +1,50 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
- ## Unreleased
5
4
 
6
- ### Unknown
7
-
8
- * Delete duplicate CODEOWNERS (#156)
9
-
10
- we have a codeowners file in root already ([`b64cdde`](https://github.com/madpah/serializable/commit/b64cdde6d4561355f7b92416dfcb36a8ff770be5))
11
-
12
-
13
-
14
- ## v2.0.0-alpha.1 (2025-01-16)
5
+ ## v2.0.0 (2025-02-09)
15
6
 
16
7
  ### Breaking
17
8
 
18
- * refactor!: rename installable `serializable` -> `py_serializable`
19
-
20
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`39bfc1a`](https://github.com/madpah/serializable/commit/39bfc1a3f20efdb75be3b14e9bfa845dc1f62142))
9
+ * refactor!: rename python package `serializable` -> `py_serializable` (#155)
21
10
 
22
- ### Chore
23
-
24
- * chore: Create CODEOWNERS ([`960331a`](https://github.com/madpah/serializable/commit/960331ad5181b64afa140d1fd0d2d59b687d782b))
25
-
26
- * chore(deps-dev): update mypy requirement from 1.13.0 to 1.14.1 (#154)
27
-
28
- Updates the requirements on [mypy](https://github.com/python/mypy) to permit the latest version.
29
- - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
30
- - [Commits](https://github.com/python/mypy/compare/v1.13.0...v1.14.1)
11
+ The python package was renamed from `serializable` to `py_serializable`.
12
+ Therefore, you need to adjust your imports.
31
13
 
32
- ---
33
- updated-dependencies:
34
- - dependency-name: mypy
35
- dependency-type: direct:development
36
- ...
14
+ The following shows a quick way to adjust imports in the most efficient way.
37
15
 
38
- Signed-off-by: dependabot[bot] <support@github.com>
39
- Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`afe70c8`](https://github.com/madpah/serializable/commit/afe70c81e20ac678bfeaedd2588083d5ba4ab4d5))
40
-
41
- * chore(deps-dev): update flake8-bugbear requirement (#150)
42
-
43
- Updates the requirements on [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) to permit the latest version.
44
- - [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
45
- - [Commits](https://github.com/PyCQA/flake8-bugbear/compare/24.10.31...24.12.12)
46
-
47
- ---
48
- updated-dependencies:
49
- - dependency-name: flake8-bugbear
50
- dependency-type: direct:development
51
- ...
52
-
53
- Signed-off-by: dependabot[bot] <support@github.com>
54
- Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`cb8a91b`](https://github.com/madpah/serializable/commit/cb8a91b6c5a42f5a46379adc272ec8fa4cc2cc37))
55
-
56
- * chore(deps-dev): update flake8-bugbear requirement (#146)
57
-
58
- Updates the requirements on [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) to permit the latest version.
59
- - [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
60
- - [Commits](https://github.com/PyCQA/flake8-bugbear/compare/24.8.19...24.10.31)
16
+ ### OLD imports
17
+ ```py
18
+ import serializable
19
+ from serializable import ViewType, XmlArraySerializationType, XmlStringSerializationType
20
+ from serializable.helpers import BaseHelper, Iso8601Date
21
+ ```
61
22
 
62
- ---
63
- updated-dependencies:
64
- - dependency-name: flake8-bugbear
65
- dependency-type: direct:development
66
- ...
23
+ ### ADJUSTED imports
24
+ ```py
25
+ import py_serializable as serializable
26
+ from py_serializable import ViewType, XmlArraySerializationType, XmlStringSerializationType
27
+ from py_serializable.helpers import BaseHelper, Iso8601Date
28
+ ```
67
29
 
68
- Signed-off-by: dependabot[bot] <support@github.com>
69
- Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`f6574e7`](https://github.com/madpah/serializable/commit/f6574e757695a4afc6922138a5e3cc8bdade2142))
70
-
71
- * chore(deps-dev): update mypy requirement from 1.12.0 to 1.13.0 (#145)
72
-
73
- Updates the requirements on [mypy](https://github.com/python/mypy) to permit the latest version.
74
- - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
75
- - [Commits](https://github.com/python/mypy/compare/v1.12.0...v1.13.0)
30
+ see migration path: <https://py-serializable.readthedocs.io/en/refactor-rename-installable-py_serializable/migration.html>
76
31
 
77
- ---
78
- updated-dependencies:
79
- - dependency-name: mypy
80
- dependency-type: direct:development
81
- ...
32
+ ----
82
33
 
83
- Signed-off-by: dependabot[bot] <support@github.com>
84
- Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`c5117ba`](https://github.com/madpah/serializable/commit/c5117ba0ef716b8cc7a3f1d639df585bba36f5e3))
85
-
86
- * chore(deps-dev): update mypy requirement from 1.11.2 to 1.12.0 (#143)
87
-
88
- Updates the requirements on [mypy](https://github.com/python/mypy) to permit the latest version.
89
- - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
90
- - [Commits](https://github.com/python/mypy/compare/v1.11.2...v1.12.0)
34
+ fixes #151
91
35
 
92
- ---
93
- updated-dependencies:
94
- - dependency-name: mypy
95
- dependency-type: direct:development
96
- ...
36
+ ---------
97
37
 
98
- Signed-off-by: dependabot[bot] <support@github.com>
99
- Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`6c354e2`](https://github.com/madpah/serializable/commit/6c354e2ef3ec276d624553e29adb705c9d9f33ec))
38
+ Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
39
+ Signed-off-by: semantic-release <semantic-release>
40
+ Co-authored-by: semantic-release <semantic-release> ([`67afaef`](https://github.com/madpah/serializable/commit/67afaef4a5e670c533409f1ccbc3d2dbb263d2de))
100
41
 
101
42
  ### Unknown
102
43
 
103
- * Merge branch 'main' into refactor/rename-installable-py_serializable ([`5b62208`](https://github.com/madpah/serializable/commit/5b622084eb016765096679451ce15801c45d707d))
104
-
105
44
  * Delete duplicate CODEOWNERS (#156)
106
45
 
107
46
  we have a codeowners file in root already ([`b64cdde`](https://github.com/madpah/serializable/commit/b64cdde6d4561355f7b92416dfcb36a8ff770be5))
108
47
 
109
- * docs
110
-
111
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`e3708ec`](https://github.com/madpah/serializable/commit/e3708ec0fbd23a3705a5fe49c8a31293bbf7446f))
112
-
113
- * docs
114
-
115
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`225b614`](https://github.com/madpah/serializable/commit/225b614346f89a04cce759fc617a42d647f8a4a9))
116
-
117
- * docs
118
-
119
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`a581861`](https://github.com/madpah/serializable/commit/a58186100361e48135b630a42bc5b5929af3dd15))
120
-
121
- * docs
122
-
123
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`2df3e21`](https://github.com/madpah/serializable/commit/2df3e21012fc9499bf47236fb85925394b3bfc2d))
124
-
125
- * style
126
-
127
- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com> ([`42cf87b`](https://github.com/madpah/serializable/commit/42cf87bb30c4cf2d19eba4a86c20fa198ff48208))
128
-
129
48
 
130
49
  ## v1.1.2 (2024-10-01)
131
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: py-serializable
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Library for serializing and deserializing Python Objects to and from JSON and XML.
5
5
  License: Apache-2.0
6
6
  Keywords: serialization,deserialization,JSON,XML
@@ -24,7 +24,7 @@ author = 'Paul Horton'
24
24
 
25
25
  # The full version, including alpha/beta/rc tags
26
26
  # !! version is managed by semantic_release
27
- release = "2.0.0"
27
+ release = "2.1.0"
28
28
 
29
29
  # -- General configuration ---------------------------------------------------
30
30
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -60,7 +58,7 @@ import typing # noqa: F401 # isort: skip
60
58
 
61
59
  # !! version is managed by semantic_release
62
60
  # do not use typing here, or else `semantic_release` might have issues finding the variable
63
- __version__ = '2.0.0'
61
+ __version__ = '2.1.0'
64
62
 
65
63
  _logger = getLogger(__name__)
66
64
  _logger.addHandler(NullHandler())
@@ -322,10 +320,10 @@ class _JsonSerializable(Protocol):
322
320
 
323
321
  _data = copy(data)
324
322
  for k, v in data.items():
323
+ del _data[k]
325
324
  decoded_k = CurrentFormatter.formatter.decode(property_name=k)
326
325
  if decoded_k in klass.ignore_during_deserialization:
327
326
  _logger.debug('Ignoring %s when deserializing %s.%s', k, cls.__module__, cls.__qualname__)
328
- del _data[k]
329
327
  continue
330
328
 
331
329
  new_key = None
@@ -338,13 +336,14 @@ class _JsonSerializable(Protocol):
338
336
  new_key = decoded_k
339
337
 
340
338
  if new_key is None:
339
+ if klass.ignore_unknown_during_deserialization:
340
+ _logger.debug('Ignoring %s when deserializing %s.%s', k, cls.__module__, cls.__qualname__)
341
+ continue
341
342
  _logger.error('Unexpected key %s/%s in data being serialized to %s.%s',
342
343
  k, decoded_k, cls.__module__, cls.__qualname__)
343
344
  raise ValueError(
344
345
  f'Unexpected key {k}/{decoded_k} in data being serialized to {cls.__module__}.{cls.__qualname__}'
345
346
  )
346
-
347
- del (_data[k])
348
347
  _data[new_key] = v
349
348
 
350
349
  for k, v in _data.items():
@@ -595,6 +594,9 @@ class _XmlSerializable(Protocol):
595
594
 
596
595
  prop_info = klass_properties.get(decoded_k)
597
596
  if not prop_info:
597
+ if klass.ignore_unknown_during_deserialization:
598
+ _logger.debug('Ignoring %s when deserializing %s.%s', decoded_k, cls.__module__, cls.__qualname__)
599
+ continue
598
600
  raise ValueError(f'Non-primitive types not supported from XML Attributes - see {decoded_k} for '
599
601
  f'{cls.__module__}.{cls.__qualname__} which has Prop Metadata: {prop_info}')
600
602
 
@@ -648,6 +650,11 @@ class _XmlSerializable(Protocol):
648
650
 
649
651
  prop_info = klass_properties.get(decoded_k)
650
652
  if not prop_info:
653
+ if klass.ignore_unknown_during_deserialization:
654
+ _logger.debug('Ignoring %s when deserializing %s.%s', decoded_k, cls.__module__, cls.__qualname__)
655
+ continue
656
+ _logger.error('Unexpected key %s/%s in data being serialized to %s.%s',
657
+ k, decoded_k, cls.__module__, cls.__qualname__)
651
658
  raise ValueError(f'{decoded_k} is not a known Property for {cls.__module__}.{cls.__qualname__}')
652
659
 
653
660
  try:
@@ -760,7 +767,12 @@ class ObjectMetadataLibrary:
760
767
 
761
768
  def __init__(self, *, klass: type, custom_name: Optional[str] = None,
762
769
  serialization_types: Optional[Iterable[SerializationType]] = None,
763
- ignore_during_deserialization: Optional[Iterable[str]] = None) -> None:
770
+ ignore_during_deserialization: Optional[Iterable[str]] = None,
771
+ ignore_unknown_during_deserialization: bool = False) -> None:
772
+ # param ignore_unknown_during_deserialization defaults to False, since we deserialize from JSON/XML
773
+ # and both have mechanisms for arbitrary content that might be intended to pass to the constructors:
774
+ # - JSON has `additionalProperties:true`
775
+ # - XML has `##any` and `##other`
764
776
  self._name = str(klass.__name__)
765
777
  self._klass = klass
766
778
  self._custom_name = custom_name
@@ -768,6 +780,7 @@ class ObjectMetadataLibrary:
768
780
  serialization_types = _DEFAULT_SERIALIZATION_TYPES
769
781
  self._serialization_types = serialization_types
770
782
  self._ignore_during_deserialization = set(ignore_during_deserialization or ())
783
+ self._ignore_unknown_during_deserialization = ignore_unknown_during_deserialization
771
784
 
772
785
  @property
773
786
  def name(self) -> str:
@@ -789,6 +802,10 @@ class ObjectMetadataLibrary:
789
802
  def ignore_during_deserialization(self) -> Set[str]:
790
803
  return self._ignore_during_deserialization
791
804
 
805
+ @property
806
+ def ignore_unknown_during_deserialization(self) -> bool:
807
+ return self._ignore_unknown_during_deserialization
808
+
792
809
  def __repr__(self) -> str:
793
810
  return f'<s.oml.SerializableClass name={self.name}>'
794
811
 
@@ -1096,14 +1113,20 @@ class ObjectMetadataLibrary:
1096
1113
  @classmethod
1097
1114
  def register_klass(cls, klass: Type[_T], custom_name: Optional[str],
1098
1115
  serialization_types: Iterable[SerializationType],
1099
- ignore_during_deserialization: Optional[Iterable[str]] = None
1116
+ ignore_during_deserialization: Optional[Iterable[str]] = None,
1117
+ ignore_unknown_during_deserialization: bool = False
1100
1118
  ) -> Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]:
1119
+ # param ignore_unknown_during_deserialization defaults to False, since we deserialize from JSON/XML
1120
+ # and both have mechanisms for arbitrary content that might be intended to pass to the constructors:
1121
+ # - JSON has `additionalProperties:true`
1122
+ # - XML has `##any` and `##other`
1101
1123
  if cls.is_klass_serializable(klass=klass):
1102
1124
  return klass
1103
1125
 
1104
1126
  cls.klass_mappings[f'{klass.__module__}.{klass.__qualname__}'] = ObjectMetadataLibrary.SerializableClass(
1105
1127
  klass=klass, serialization_types=serialization_types,
1106
- ignore_during_deserialization=ignore_during_deserialization
1128
+ ignore_during_deserialization=ignore_during_deserialization,
1129
+ ignore_unknown_during_deserialization=ignore_unknown_during_deserialization
1107
1130
  )
1108
1131
 
1109
1132
  qualified_class_name = f'{klass.__module__}.{klass.__qualname__}'
@@ -1243,7 +1266,8 @@ def serializable_class(
1243
1266
  cls: Literal[None] = None, *,
1244
1267
  name: Optional[str] = ...,
1245
1268
  serialization_types: Optional[Iterable[SerializationType]] = ...,
1246
- ignore_during_deserialization: Optional[Iterable[str]] = ...
1269
+ ignore_during_deserialization: Optional[Iterable[str]] = ...,
1270
+ ignore_unknown_during_deserialization: bool = ...
1247
1271
  ) -> Callable[[Type[_T]], Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]]:
1248
1272
  ...
1249
1273
 
@@ -1253,7 +1277,8 @@ def serializable_class( # type:ignore[misc] # mypy on py37
1253
1277
  cls: Type[_T], *,
1254
1278
  name: Optional[str] = ...,
1255
1279
  serialization_types: Optional[Iterable[SerializationType]] = ...,
1256
- ignore_during_deserialization: Optional[Iterable[str]] = ...
1280
+ ignore_during_deserialization: Optional[Iterable[str]] = ...,
1281
+ ignore_unknown_during_deserialization: bool = ...
1257
1282
  ) -> Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]:
1258
1283
  ...
1259
1284
 
@@ -1262,7 +1287,8 @@ def serializable_class(
1262
1287
  cls: Optional[Type[_T]] = None, *,
1263
1288
  name: Optional[str] = None,
1264
1289
  serialization_types: Optional[Iterable[SerializationType]] = None,
1265
- ignore_during_deserialization: Optional[Iterable[str]] = None
1290
+ ignore_during_deserialization: Optional[Iterable[str]] = None,
1291
+ ignore_unknown_during_deserialization: bool = False
1266
1292
  ) -> Union[
1267
1293
  Callable[[Type[_T]], Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]],
1268
1294
  Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]
@@ -1274,15 +1300,22 @@ def serializable_class(
1274
1300
  :param name: Alternative name to use for this Class
1275
1301
  :param serialization_types: Serialization Types that are to be supported for this class.
1276
1302
  :param ignore_during_deserialization: List of properties/elements to ignore during deserialization
1303
+ :param ignore_unknown_during_deserialization: Whether to ignore all properties/elements/attributes that are unknown
1304
+ to the class during deserialization
1277
1305
  :return:
1278
1306
  """
1307
+ # param ignore_unknown_during_deserialization defaults to False, since we deserialize from JSON/XML
1308
+ # and both have mechanisms for arbitrary content that might be intended to pass to the constructors:
1309
+ # - JSON has `additionalProperties:true`
1310
+ # - XML has `##any` and `##other`
1279
1311
  if serialization_types is None:
1280
1312
  serialization_types = _DEFAULT_SERIALIZATION_TYPES
1281
1313
 
1282
1314
  def decorate(kls: Type[_T]) -> Intersection[Type[_T], Type[_JsonSerializable], Type[_XmlSerializable]]:
1283
1315
  ObjectMetadataLibrary.register_klass(
1284
1316
  klass=kls, custom_name=name, serialization_types=serialization_types or [],
1285
- ignore_during_deserialization=ignore_during_deserialization
1317
+ ignore_during_deserialization=ignore_during_deserialization,
1318
+ ignore_unknown_during_deserialization=ignore_unknown_during_deserialization
1286
1319
  )
1287
1320
  return kls
1288
1321
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
5
5
 
6
6
  [tool.poetry]
7
7
  name = "py-serializable"
8
- version = "2.0.0"
8
+ version = "2.1.0"
9
9
  description = "Library for serializing and deserializing Python Objects to and from JSON and XML."
10
10
  authors = ["Paul Horton <paul.horton@owasp.org>"]
11
11
  maintainers = [
@@ -64,13 +64,14 @@ xmldiff = "2.7.0"
64
64
  mypy = "1.14.1"
65
65
  autopep8 = "2.3.1"
66
66
  isort = "5.13.2"
67
- flake8 = { version="7.1.1", python=">=3.8.1" }
67
+ flake8 = { version="7.1.2", python=">=3.8.1" }
68
68
  flake8-annotations = { version="3.1.1", python=">=3.8.1" }
69
69
  flake8-bugbear = { version="24.12.12", python=">=3.8.1" }
70
70
  flake8-isort = "6.1.1"
71
71
  flake8-quotes = "3.4.0"
72
72
  flake8-use-fstring = "1.4"
73
73
  flake8-logging = "1.6.0"
74
+ pyupgrade = { version="3.20.0", python=">=3.9" }
74
75
 
75
76
 
76
77
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This file is part of py-serializable
4
2
  #
5
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -62,7 +60,7 @@ class BaseTestCase(TestCase):
62
60
  f'There are XML differences: {diff_results!r}\n- {a!s}\n+ {b!s}')
63
61
 
64
62
 
65
- class DeepCompareMixin(object):
63
+ class DeepCompareMixin:
66
64
  def assertDeepEqual(self: Union[TestCase, 'DeepCompareMixin'],
67
65
  first: Any, second: Any, msg: Optional[str] = None) -> None:
68
66
  """costly compare, but very verbose"""
@@ -0,0 +1 @@
1
+ <book xmlns="http://the.phoenix.project/testing/defaultNS" isbnNumber="978-1942788294"><id>f3758bf0-0ff7-4366-a5e5-c209d4352b2d</id><title>{X} The Phoenix Project</title><edition number="5">5th Anniversary Limited Edition</edition><publishDate>2018-04-16</publishDate><author>Karl Ranseier</author><type>fiction</type><publisher><name>IT Revolution Press LLC</name></publisher><chapters><chapter><number>1</number><title>Tuesday, September 2</title></chapter><chapter><number>2</number><title>Tuesday, September 2</title></chapter><chapter><number>3</number><title>Tuesday, September 2</title></chapter><chapter><number>4</number><title>Wednesday, September 3</title></chapter></chapters><rating>9.8</rating></book>
@@ -0,0 +1 @@
1
+ <ns0:book xmlns:ns0="http://the.phoenix.project/testing/defaultNS" ns0:isbnNumber="978-1942788294"><ns0:id>f3758bf0-0ff7-4366-a5e5-c209d4352b2d</ns0:id><ns0:title>{X} The Phoenix Project</ns0:title><ns0:edition ns0:number="5">5th Anniversary Limited Edition</ns0:edition><ns0:publishDate>2018-04-16</ns0:publishDate><ns0:author>Karl Ranseier</ns0:author><ns0:type>fiction</ns0:type><ns0:publisher><ns0:name>IT Revolution Press LLC</ns0:name></ns0:publisher><ns0:chapters><ns0:chapter><ns0:number>1</ns0:number><ns0:title>Tuesday, September 2</ns0:title></ns0:chapter><ns0:chapter><ns0:number>2</ns0:number><ns0:title>Tuesday, September 2</ns0:title></ns0:chapter><ns0:chapter><ns0:number>3</ns0:number><ns0:title>Tuesday, September 2</ns0:title></ns0:chapter><ns0:chapter><ns0:number>4</ns0:number><ns0:title>Wednesday, September 3</ns0:title></ns0:chapter></ns0:chapters><ns0:rating>9.8</ns0:rating></ns0:book>
@@ -0,0 +1,54 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+ <book xmlns="http://the.phoenix.project/testing/defaultNS"
3
+ xmlns:foo="https://example.com/foo"
4
+ something_to_be_ignored="foo"
5
+ isbnNumber="978-1942788294"
6
+ ignore_me="bar"
7
+ >
8
+ <!-- some attributes are registered to be ignored -->
9
+ <id>f3758bf0-0ff7-4366-a5e5-c209d4352b2d</id>
10
+ <title>{X} The Phoenix Project</title>
11
+ <edition number="5">5th Anniversary Limited Edition</edition>
12
+ <publishDate>2018-04-16</publishDate>
13
+ <author>Kevin Behr</author>
14
+ <author>George Spafford</author>
15
+ <author>Gene Kim</author>
16
+ <type>fiction</type>
17
+ <publisher foo:my-other-attribute="my-value"
18
+ unknown-other-attribute="some-value"
19
+ >
20
+ <address>10 Downing Street</address>
21
+ <name>IT Revolution Press LLC</name>
22
+ </publisher>
23
+ <references>
24
+ <reference ref="my-ref-2">
25
+ <reference ref="sub-ref-3"/>
26
+ <reference ref="sub-ref-1"/>
27
+ </reference>
28
+ <reference ref="my-ref-1"/>
29
+ <reference ref="my-ref-3">
30
+ <reference ref="sub-ref-2"/>
31
+ </reference>
32
+ </references>
33
+ <chapters>
34
+ <chapter>
35
+ <number>1</number>
36
+ <title>Tuesday, September 2</title>
37
+ </chapter>
38
+ <chapter>
39
+ <number>2</number>
40
+ <title>Tuesday, September 2</title>
41
+ </chapter>
42
+ <chapter>
43
+ <number>3</number>
44
+ <title>Tuesday, September 2</title>
45
+ </chapter>
46
+ <chapter>
47
+ <number>4</number>
48
+ <title>Wednesday, September 3</title>
49
+ </chapter>
50
+ </chapters>
51
+ <rating>9.8</rating>
52
+ <stockId>stock-id-1</stockId>
53
+ <stockId>stock-id-2</stockId>
54
+ </book>
@@ -0,0 +1,59 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+ <book xmlns="http://the.phoenix.project/testing/defaultNS"
3
+ xmlns:foo="https://example.com/foo"
4
+ isbnNumber="978-1942788294"
5
+ >
6
+ <!-- some elements are registered to be ignored -->
7
+ <something_to_be_ignored>foo</something_to_be_ignored>>
8
+ <id>f3758bf0-0ff7-4366-a5e5-c209d4352b2d</id>
9
+ <title>{X} The Phoenix Project</title>
10
+ <edition number="5">5th Anniversary Limited Edition</edition>
11
+ <publishDate>2018-04-16</publishDate>
12
+ <author>Gene Kim</author>
13
+ <author>George Spafford</author>
14
+ <author>Kevin Behr</author>
15
+ <type>fiction</type>
16
+ <ignore_me>bar</ignore_me>
17
+ <publisher>
18
+ <address>10 Downing Street</address>
19
+ <foo:my-unknown-element>some-value</foo:my-unknown-element>
20
+ <other-unknwon-elemment-bar xmlns="https://example.com/bar"
21
+ bar-thing="the-value"
22
+ >
23
+ <bar-elem>some-other-value</bar-elem>
24
+ </other-unknwon-elemment-bar>
25
+ <name>IT Revolution Press LLC</name>
26
+ </publisher>
27
+ <references>
28
+ <reference ref="my-ref-2">
29
+ <reference ref="sub-ref-3"/>
30
+ <reference ref="sub-ref-1"/>
31
+ </reference>
32
+ <reference ref="my-ref-3">
33
+ <reference ref="sub-ref-2"/>
34
+ </reference>
35
+ <reference ref="my-ref-1"/>
36
+ </references>
37
+ <chapters>
38
+ <chapter>
39
+ <number>1</number>
40
+ <title>Tuesday, September 2</title>
41
+ </chapter>
42
+ <chapter>
43
+ <number>2</number>
44
+ <title>Tuesday, September 2</title>
45
+ </chapter>
46
+ <chapter>
47
+ <number>3</number>
48
+ <title>Tuesday, September 2</title>
49
+ </chapter>
50
+ <chapter>
51
+ <number>4</number>
52
+ <title>Wednesday, September 3</title>
53
+ </chapter>
54
+ </chapters>
55
+ <rating>9.8</rating>
56
+ <stockId>stock-id-2</stockId>
57
+ <stockId>stock-id-1</stockId>
58
+ <ignored>bazz</ignored>
59
+ </book>
@@ -0,0 +1,66 @@
1
+ {
2
+ "$comment": "some properties are registered as ignored",
3
+ "something_to_be_ignored": "foo",
4
+ "authors": [
5
+ "Kevin Behr",
6
+ "Gene Kim",
7
+ "George Spafford"
8
+ ],
9
+ "chapters": [
10
+ {
11
+ "number": 1,
12
+ "title": "Tuesday, September 2"
13
+ },
14
+ {
15
+ "number": 2,
16
+ "title": "Tuesday, September 2"
17
+ },
18
+ {
19
+ "number": 3,
20
+ "title": "Tuesday, September 2"
21
+ },
22
+ {
23
+ "number": 4,
24
+ "title": "Wednesday, September 3"
25
+ }
26
+ ],
27
+ "ignored": "bar",
28
+ "edition": {
29
+ "name": "5th Anniversary Limited Edition",
30
+ "number": 5
31
+ },
32
+ "id": "f3758bf0-0ff7-4366-a5e5-c209d4352b2d",
33
+ "isbnNumber": "978-1942788294",
34
+ "publishDate": "2018-04-16",
35
+ "publisher": {
36
+ "address": "10 Downing Street",
37
+ "name": "IT Revolution Press LLC",
38
+ "other-unknown-property": "my-value"
39
+ },
40
+ "rating": 9.8,
41
+ "references": [
42
+ {
43
+ "reference": "my-ref-3",
44
+ "refersTo": [
45
+ "sub-ref-2"
46
+ ]
47
+ },
48
+ {
49
+ "reference": "my-ref-1"
50
+ },
51
+ {
52
+ "reference": "my-ref-2",
53
+ "refersTo": [
54
+ "sub-ref-1",
55
+ "sub-ref-3"
56
+ ]
57
+ }
58
+ ],
59
+ "stockIds": [
60
+ "stock-id-1",
61
+ "stock-id-2"
62
+ ],
63
+ "title": "{J} The Phoenix Project",
64
+ "type": "fiction",
65
+ "ignore_me": "bazz"
66
+ }