marshmallow 3.26.1__tar.gz → 3.26.2__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 (91) hide show
  1. {marshmallow-3.26.1 → marshmallow-3.26.2}/CHANGELOG.rst +8 -0
  2. {marshmallow-3.26.1 → marshmallow-3.26.2}/PKG-INFO +3 -2
  3. {marshmallow-3.26.1 → marshmallow-3.26.2}/pyproject.toml +2 -2
  4. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/error_store.py +23 -12
  5. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/schema.py +2 -2
  6. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_error_store.py +17 -1
  7. {marshmallow-3.26.1 → marshmallow-3.26.2}/CONTRIBUTING.rst +0 -0
  8. {marshmallow-3.26.1 → marshmallow-3.26.2}/LICENSE +0 -0
  9. {marshmallow-3.26.1 → marshmallow-3.26.2}/NOTICE +0 -0
  10. {marshmallow-3.26.1 → marshmallow-3.26.2}/README.rst +0 -0
  11. {marshmallow-3.26.1 → marshmallow-3.26.2}/SECURITY.md +0 -0
  12. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/.gitignore +0 -0
  13. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/apple-touch-icon.png +0 -0
  14. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/custom.css +0 -0
  15. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/favicon.ico +0 -0
  16. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/marshmallow-logo-200.png +0 -0
  17. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/marshmallow-logo-with-title-for-dark-theme.png +0 -0
  18. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/marshmallow-logo-with-title.png +0 -0
  19. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/_static/marshmallow-logo.png +0 -0
  20. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/api_reference.rst +0 -0
  21. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/authors.rst +0 -0
  22. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/changelog.rst +0 -0
  23. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/code_of_conduct.rst +0 -0
  24. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/conf.py +0 -0
  25. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/contributing.rst +0 -0
  26. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/custom_fields.rst +0 -0
  27. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/dashing.json +0 -0
  28. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/donate.rst +0 -0
  29. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/examples/index.rst +0 -0
  30. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/examples/inflection.rst +0 -0
  31. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/examples/quotes_api.rst +0 -0
  32. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/examples/validating_package_json.rst +0 -0
  33. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/custom_error_handling.rst +0 -0
  34. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/custom_error_messages.rst +0 -0
  35. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/custom_options.rst +0 -0
  36. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/index.rst +0 -0
  37. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/overriding_attribute_access.rst +0 -0
  38. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/pre_and_post_processing_methods.rst +0 -0
  39. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/schema_validation.rst +0 -0
  40. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/using_context.rst +0 -0
  41. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/extending/using_original_input_data.rst +0 -0
  42. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/index.rst +0 -0
  43. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/install.rst +0 -0
  44. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/kudos.rst +0 -0
  45. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/license.rst +0 -0
  46. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.class_registry.rst +0 -0
  47. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.decorators.rst +0 -0
  48. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.error_store.rst +0 -0
  49. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.exceptions.rst +0 -0
  50. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.fields.rst +0 -0
  51. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.schema.rst +0 -0
  52. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.types.rst +0 -0
  53. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.utils.rst +0 -0
  54. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/marshmallow.validate.rst +0 -0
  55. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/nesting.rst +0 -0
  56. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/quickstart.rst +0 -0
  57. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/top_level.rst +0 -0
  58. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/upgrading.rst +0 -0
  59. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/whos_using.rst +0 -0
  60. {marshmallow-3.26.1 → marshmallow-3.26.2}/docs/why.rst +0 -0
  61. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/__init__.py +0 -0
  62. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/base.py +0 -0
  63. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/class_registry.py +0 -0
  64. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/decorators.py +0 -0
  65. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/exceptions.py +0 -0
  66. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/fields.py +0 -0
  67. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/orderedset.py +0 -0
  68. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/py.typed +0 -0
  69. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/types.py +0 -0
  70. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/utils.py +0 -0
  71. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/validate.py +0 -0
  72. {marshmallow-3.26.1 → marshmallow-3.26.2}/src/marshmallow/warnings.py +0 -0
  73. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/__init__.py +0 -0
  74. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/base.py +0 -0
  75. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/conftest.py +0 -0
  76. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/foo_serializer.py +0 -0
  77. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/mypy_test_cases/test_class_registry.py +0 -0
  78. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/mypy_test_cases/test_schema.py +0 -0
  79. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/mypy_test_cases/test_validation_error.py +0 -0
  80. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_decorators.py +0 -0
  81. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_deserialization.py +0 -0
  82. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_exceptions.py +0 -0
  83. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_fields.py +0 -0
  84. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_options.py +0 -0
  85. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_registry.py +0 -0
  86. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_schema.py +0 -0
  87. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_serialization.py +0 -0
  88. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_utils.py +0 -0
  89. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_validate.py +0 -0
  90. {marshmallow-3.26.1 → marshmallow-3.26.2}/tests/test_version_attributes.py +0 -0
  91. {marshmallow-3.26.1 → marshmallow-3.26.2}/tox.ini +0 -0
@@ -1,6 +1,14 @@
1
1
  Changelog
2
2
  ---------
3
3
 
4
+ 3.26.2 (2025-12-19)
5
+ ++++++++++++++++++
6
+
7
+ Bug fixes:
8
+
9
+ - :cve:`CVE-2025-68480`: Merge error store messages without rebuilding collections.
10
+ Thanks 카푸치노 for reporting and :user:`deckar01` for the fix.
11
+
4
12
  3.26.1 (2025-02-03)
5
13
  *******************
6
14
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: marshmallow
3
- Version: 3.26.1
3
+ Version: 3.26.2
4
4
  Summary: A lightweight library for converting complex datatypes to and from native Python datatypes.
5
5
  Author-email: Steven Loria <sloria1@gmail.com>
6
6
  Maintainer-email: Steven Loria <sloria1@gmail.com>, Jérôme Lafréchoux <jerome@jolimont.fr>, Jared Deckard <jared@shademaps.com>
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
+ License-File: LICENSE
18
19
  Requires-Dist: packaging>=17.0
19
20
  Requires-Dist: marshmallow[tests] ; extra == "dev"
20
21
  Requires-Dist: tox ; extra == "dev"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "marshmallow"
3
- version = "3.26.1"
3
+ version = "3.26.2"
4
4
  description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
5
5
  readme = "README.rst"
6
6
  license = { file = "LICENSE" }
@@ -121,7 +121,7 @@ ignore = [
121
121
  [tool.mypy]
122
122
  files = ["src", "tests", "examples"]
123
123
  ignore_missing_imports = true
124
- warn_unreachable = true
124
+ warn_unreachable = false
125
125
  warn_unused_ignores = true
126
126
  warn_redundant_casts = true
127
127
  no_implicit_optional = true
@@ -18,6 +18,7 @@ class ErrorStore:
18
18
  # field error -> store/merge error messages under field name key
19
19
  # schema error -> if string or list, store/merge under _schema key
20
20
  # -> if dict, store/merge with other top-level keys
21
+ messages = copy_containers(messages)
21
22
  if field_name != SCHEMA or not isinstance(messages, dict):
22
23
  messages = {field_name: messages}
23
24
  if index is not None:
@@ -25,6 +26,14 @@ class ErrorStore:
25
26
  self.errors = merge_errors(self.errors, messages)
26
27
 
27
28
 
29
+ def copy_containers(errors):
30
+ if isinstance(errors, list):
31
+ return [copy_containers(val) for val in errors]
32
+ if isinstance(errors, dict):
33
+ return {key: copy_containers(val) for key, val in errors.items()}
34
+ return errors
35
+
36
+
28
37
  def merge_errors(errors1, errors2): # noqa: PLR0911
29
38
  """Deeply merge two error messages.
30
39
 
@@ -37,24 +46,26 @@ def merge_errors(errors1, errors2): # noqa: PLR0911
37
46
  return errors1
38
47
  if isinstance(errors1, list):
39
48
  if isinstance(errors2, list):
40
- return errors1 + errors2
49
+ errors1.extend(errors2)
50
+ return errors1
41
51
  if isinstance(errors2, dict):
42
- return dict(errors2, **{SCHEMA: merge_errors(errors1, errors2.get(SCHEMA))})
43
- return [*errors1, errors2]
52
+ errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA))
53
+ return errors2
54
+ errors1.append(errors2)
55
+ return errors1
44
56
  if isinstance(errors1, dict):
45
- if isinstance(errors2, list):
46
- return dict(errors1, **{SCHEMA: merge_errors(errors1.get(SCHEMA), errors2)})
47
57
  if isinstance(errors2, dict):
48
- errors = dict(errors1)
49
58
  for key, val in errors2.items():
50
- if key in errors:
51
- errors[key] = merge_errors(errors[key], val)
59
+ if key in errors1:
60
+ errors1[key] = merge_errors(errors1[key], val)
52
61
  else:
53
- errors[key] = val
54
- return errors
55
- return dict(errors1, **{SCHEMA: merge_errors(errors1.get(SCHEMA), errors2)})
62
+ errors1[key] = val
63
+ return errors1
64
+ errors1[SCHEMA] = merge_errors(errors1.get(SCHEMA), errors2)
65
+ return errors1
56
66
  if isinstance(errors2, list):
57
67
  return [errors1, *errors2]
58
68
  if isinstance(errors2, dict):
59
- return dict(errors2, **{SCHEMA: merge_errors(errors1, errors2.get(SCHEMA))})
69
+ errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA))
70
+ return errors2
60
71
  return [errors1, errors2]
@@ -374,7 +374,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
374
374
 
375
375
  class MySchema2(Schema):
376
376
  # Type checkers will check attributes
377
- class Meta(Schema.Opts):
377
+ class Meta(Schema.Meta):
378
378
  additional = True # Incompatible types in assignment
379
379
 
380
380
  .. versionremoved:: 3.0.0b7 Remove ``strict``.
@@ -1139,7 +1139,7 @@ class Schema(base.SchemaABC, metaclass=SchemaMeta):
1139
1139
  msg = (
1140
1140
  f'Field for "{field_name}" must be declared as a '
1141
1141
  "Field instance, not a class. "
1142
- f'Did you mean "fields.{field_obj.__name__}()"?' # type: ignore[attr-defined]
1142
+ f'Did you mean "fields.{field_obj.__name__}()"?'
1143
1143
  )
1144
1144
  raise TypeError(msg) from error
1145
1145
  raise
@@ -1,7 +1,7 @@
1
1
  from typing import NamedTuple
2
2
 
3
3
  from marshmallow import missing
4
- from marshmallow.error_store import merge_errors
4
+ from marshmallow.error_store import ErrorStore, merge_errors
5
5
 
6
6
 
7
7
  def test_missing_is_falsy():
@@ -149,3 +149,19 @@ class TestMergeErrors:
149
149
  assert merge_errors(
150
150
  {"field1": {"field2": "error1"}}, {"field1": {"field2": "error2"}}
151
151
  ) == {"field1": {"field2": ["error1", "error2"]}}
152
+
153
+ def test_list_not_changed(self):
154
+ store = ErrorStore()
155
+ message = ["foo"]
156
+ store.store_error(message)
157
+ store.store_error(message)
158
+ assert message == ["foo"]
159
+ assert store.errors == {"_schema": ["foo", "foo"]}
160
+
161
+ def test_dict_not_changed(self):
162
+ store = ErrorStore()
163
+ message = {"foo": ["bar"]}
164
+ store.store_error(message)
165
+ store.store_error(message)
166
+ assert message == {"foo": ["bar"]}
167
+ assert store.errors == {"foo": ["bar", "bar"]}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes