multidict 6.6.3__tar.gz → 6.6.4__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.

Potentially problematic release.


This version of multidict might be problematic. Click here for more details.

Files changed (109) hide show
  1. {multidict-6.6.3 → multidict-6.6.4}/CHANGES.rst +39 -0
  2. {multidict-6.6.3/multidict.egg-info → multidict-6.6.4}/PKG-INFO +1 -1
  3. {multidict-6.6.3 → multidict-6.6.4}/multidict/__init__.py +1 -1
  4. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/hashtable.h +1 -1
  5. {multidict-6.6.3 → multidict-6.6.4/multidict.egg-info}/PKG-INFO +1 -1
  6. {multidict-6.6.3 → multidict-6.6.4}/multidict.egg-info/SOURCES.txt +1 -0
  7. {multidict-6.6.3 → multidict-6.6.4}/pytest.ini +1 -1
  8. {multidict-6.6.3 → multidict-6.6.4}/requirements/pytest.txt +1 -0
  9. multidict-6.6.4/tests/isolated/multidict_pop.py +80 -0
  10. {multidict-6.6.3 → multidict-6.6.4}/tests/test_leaks.py +1 -0
  11. {multidict-6.6.3 → multidict-6.6.4}/.coveragerc +0 -0
  12. {multidict-6.6.3 → multidict-6.6.4}/CHANGES/.TEMPLATE.rst +0 -0
  13. {multidict-6.6.3 → multidict-6.6.4}/CHANGES/.gitignore +0 -0
  14. {multidict-6.6.3 → multidict-6.6.4}/CHANGES/README.rst +0 -0
  15. {multidict-6.6.3 → multidict-6.6.4}/LICENSE +0 -0
  16. {multidict-6.6.3 → multidict-6.6.4}/MANIFEST.in +0 -0
  17. {multidict-6.6.3 → multidict-6.6.4}/Makefile +0 -0
  18. {multidict-6.6.3 → multidict-6.6.4}/README.rst +0 -0
  19. {multidict-6.6.3 → multidict-6.6.4}/docs/Makefile +0 -0
  20. {multidict-6.6.3 → multidict-6.6.4}/docs/benchmark.rst +0 -0
  21. {multidict-6.6.3 → multidict-6.6.4}/docs/changes.rst +0 -0
  22. {multidict-6.6.3 → multidict-6.6.4}/docs/conf.py +0 -0
  23. {multidict-6.6.3 → multidict-6.6.4}/docs/index.rst +0 -0
  24. {multidict-6.6.3 → multidict-6.6.4}/docs/make.bat +0 -0
  25. {multidict-6.6.3 → multidict-6.6.4}/docs/multidict.rst +0 -0
  26. {multidict-6.6.3 → multidict-6.6.4}/docs/spelling_wordlist.txt +0 -0
  27. {multidict-6.6.3 → multidict-6.6.4}/multidict/_abc.py +0 -0
  28. {multidict-6.6.3 → multidict-6.6.4}/multidict/_compat.py +0 -0
  29. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multidict.c +0 -0
  30. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multidict_py.py +0 -0
  31. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/dict.h +0 -0
  32. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/htkeys.h +0 -0
  33. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/istr.h +0 -0
  34. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/iter.h +0 -0
  35. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/parser.h +0 -0
  36. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/pythoncapi_compat.h +0 -0
  37. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/state.h +0 -0
  38. {multidict-6.6.3 → multidict-6.6.4}/multidict/_multilib/views.h +0 -0
  39. {multidict-6.6.3 → multidict-6.6.4}/multidict/py.typed +0 -0
  40. {multidict-6.6.3 → multidict-6.6.4}/multidict.egg-info/dependency_links.txt +0 -0
  41. {multidict-6.6.3 → multidict-6.6.4}/multidict.egg-info/requires.txt +0 -0
  42. {multidict-6.6.3 → multidict-6.6.4}/multidict.egg-info/top_level.txt +0 -0
  43. {multidict-6.6.3 → multidict-6.6.4}/pyproject.toml +0 -0
  44. {multidict-6.6.3 → multidict-6.6.4}/requirements/ci.txt +0 -0
  45. {multidict-6.6.3 → multidict-6.6.4}/requirements/dev.txt +0 -0
  46. {multidict-6.6.3 → multidict-6.6.4}/requirements/doc-spelling.txt +0 -0
  47. {multidict-6.6.3 → multidict-6.6.4}/requirements/doc.txt +0 -0
  48. {multidict-6.6.3 → multidict-6.6.4}/requirements/lint.txt +0 -0
  49. {multidict-6.6.3 → multidict-6.6.4}/requirements/towncrier.txt +0 -0
  50. {multidict-6.6.3 → multidict-6.6.4}/requirements/wheel.txt +0 -0
  51. {multidict-6.6.3 → multidict-6.6.4}/setup.cfg +0 -0
  52. {multidict-6.6.3 → multidict-6.6.4}/setup.py +0 -0
  53. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.0 +0 -0
  54. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.1 +0 -0
  55. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.2 +0 -0
  56. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.3 +0 -0
  57. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.4 +0 -0
  58. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-c.pickle.5 +0 -0
  59. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.0 +0 -0
  60. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.1 +0 -0
  61. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.2 +0 -0
  62. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.3 +0 -0
  63. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.4 +0 -0
  64. {multidict-6.6.3 → multidict-6.6.4}/tests/cimultidict-py.pickle.5 +0 -0
  65. {multidict-6.6.3 → multidict-6.6.4}/tests/conftest.py +0 -0
  66. {multidict-6.6.3 → multidict-6.6.4}/tests/gen_pickles.py +0 -0
  67. {multidict-6.6.3 → multidict-6.6.4}/tests/isolated/multidict_extend_dict.py +0 -0
  68. {multidict-6.6.3 → multidict-6.6.4}/tests/isolated/multidict_extend_multidict.py +0 -0
  69. {multidict-6.6.3 → multidict-6.6.4}/tests/isolated/multidict_extend_tuple.py +0 -0
  70. {multidict-6.6.3 → multidict-6.6.4}/tests/isolated/multidict_update_multidict.py +0 -0
  71. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.0 +0 -0
  72. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.1 +0 -0
  73. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.2 +0 -0
  74. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.3 +0 -0
  75. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.4 +0 -0
  76. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-c.pickle.5 +0 -0
  77. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.0 +0 -0
  78. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.1 +0 -0
  79. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.2 +0 -0
  80. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.3 +0 -0
  81. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.4 +0 -0
  82. {multidict-6.6.3 → multidict-6.6.4}/tests/istr-py.pickle.5 +0 -0
  83. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.0 +0 -0
  84. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.1 +0 -0
  85. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.2 +0 -0
  86. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.3 +0 -0
  87. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.4 +0 -0
  88. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-c.pickle.5 +0 -0
  89. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.0 +0 -0
  90. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.1 +0 -0
  91. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.2 +0 -0
  92. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.3 +0 -0
  93. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.4 +0 -0
  94. {multidict-6.6.3 → multidict-6.6.4}/tests/multidict-py.pickle.5 +0 -0
  95. {multidict-6.6.3 → multidict-6.6.4}/tests/test_abc.py +0 -0
  96. {multidict-6.6.3 → multidict-6.6.4}/tests/test_circular_imports.py +0 -0
  97. {multidict-6.6.3 → multidict-6.6.4}/tests/test_copy.py +0 -0
  98. {multidict-6.6.3 → multidict-6.6.4}/tests/test_guard.py +0 -0
  99. {multidict-6.6.3 → multidict-6.6.4}/tests/test_incorrect_args.py +0 -0
  100. {multidict-6.6.3 → multidict-6.6.4}/tests/test_istr.py +0 -0
  101. {multidict-6.6.3 → multidict-6.6.4}/tests/test_multidict.py +0 -0
  102. {multidict-6.6.3 → multidict-6.6.4}/tests/test_multidict_benchmarks.py +0 -0
  103. {multidict-6.6.3 → multidict-6.6.4}/tests/test_mutable_multidict.py +0 -0
  104. {multidict-6.6.3 → multidict-6.6.4}/tests/test_mypy.py +0 -0
  105. {multidict-6.6.3 → multidict-6.6.4}/tests/test_pickle.py +0 -0
  106. {multidict-6.6.3 → multidict-6.6.4}/tests/test_types.py +0 -0
  107. {multidict-6.6.3 → multidict-6.6.4}/tests/test_update.py +0 -0
  108. {multidict-6.6.3 → multidict-6.6.4}/tests/test_version.py +0 -0
  109. {multidict-6.6.3 → multidict-6.6.4}/tests/test_views_benchmarks.py +0 -0
@@ -14,6 +14,45 @@ Changelog
14
14
 
15
15
  .. towncrier release notes start
16
16
 
17
+ 6.6.4
18
+ =====
19
+
20
+ *(2025-08-11)*
21
+
22
+
23
+ Bug fixes
24
+ ---------
25
+
26
+ - Fixed ``MutliDict`` & ``CIMultiDict`` memory leak when deleting values or clearing them
27
+ -- by :user:`Vizonex`
28
+
29
+ *Related issues and pull requests on GitHub:*
30
+ :issue:`1233`.
31
+
32
+
33
+ Contributor-facing changes
34
+ --------------------------
35
+
36
+ - The type preciseness coverage report generated by `MyPy
37
+ <https://mypy-lang.org>`__ is now uploaded to `Coveralls
38
+ <https://coveralls.io/github/aio-libs/multidict>`__ and
39
+ will not be included in the `Codecov views
40
+ <https://app.codecov.io/gh/aio-libs/multidict>`__ going forward
41
+ -- by :user:`webknjaz`.
42
+
43
+ *Related issues and pull requests on GitHub:*
44
+ :issue:`1122`, :issue:`1231`.
45
+
46
+ - Added memory leak test for popping or deleting attributes from a multidict to prevent future issues or bogus claims.
47
+ -- by :user:`Vizonex`
48
+
49
+ *Related issues and pull requests on GitHub:*
50
+ :issue:`1233`.
51
+
52
+
53
+ ----
54
+
55
+
17
56
  6.6.3
18
57
  =====
19
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multidict
3
- Version: 6.6.3
3
+ Version: 6.6.4
4
4
  Summary: multidict implementation
5
5
  Home-page: https://github.com/aio-libs/multidict
6
6
  Author: Andrew Svetlov
@@ -22,7 +22,7 @@ __all__ = (
22
22
  "getversion",
23
23
  )
24
24
 
25
- __version__ = "6.6.3"
25
+ __version__ = "6.6.4"
26
26
 
27
27
 
28
28
  if TYPE_CHECKING or not USE_EXTENSIONS:
@@ -1877,7 +1877,7 @@ md_traverse(MultiDictObject *md, visitproc visit, void *arg)
1877
1877
  static inline int
1878
1878
  md_clear(MultiDictObject *md)
1879
1879
  {
1880
- if (md->used == 0) {
1880
+ if (md->keys == NULL || md->keys == &empty_htkeys) {
1881
1881
  return 0;
1882
1882
  }
1883
1883
  md->version = NEXT_VERSION(md->state);
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multidict
3
- Version: 6.6.3
3
+ Version: 6.6.4
4
4
  Summary: multidict implementation
5
5
  Home-page: https://github.com/aio-libs/multidict
6
6
  Author: Andrew Svetlov
@@ -104,4 +104,5 @@ tests/test_views_benchmarks.py
104
104
  tests/isolated/multidict_extend_dict.py
105
105
  tests/isolated/multidict_extend_multidict.py
106
106
  tests/isolated/multidict_extend_tuple.py
107
+ tests/isolated/multidict_pop.py
107
108
  tests/isolated/multidict_update_multidict.py
@@ -41,7 +41,7 @@ doctest_optionflags = ALLOW_UNICODE ELLIPSIS
41
41
  # Marks tests with an empty parameterset as xfail(run=False)
42
42
  empty_parameter_set_mark = xfail
43
43
 
44
- faulthandler_timeout = 60
44
+ faulthandler_timeout = 90
45
45
 
46
46
  filterwarnings =
47
47
  error
@@ -2,3 +2,4 @@ objgraph==3.6.2
2
2
  pytest==8.4.0
3
3
  pytest-codspeed==3.2.0
4
4
  pytest-cov==6.1.0
5
+ psutil==7.0.0
@@ -0,0 +1,80 @@
1
+ # Test for memory leaks surrounding deletion of values or
2
+ # bad cleanups.
3
+ # SEE: https://github.com/aio-libs/multidict/issues/1232
4
+ # We want to make sure that bad predictions or bougus claims
5
+ # of memory leaks can be prevented in the future.
6
+
7
+ import gc
8
+ import psutil
9
+ import os
10
+ from multidict import MultiDict
11
+
12
+
13
+ def trim_ram() -> None:
14
+ """Forces python garbage collection."""
15
+ gc.collect()
16
+
17
+
18
+ process = psutil.Process(os.getpid())
19
+
20
+
21
+ def get_memory_usage() -> int:
22
+ memory_info = process.memory_info()
23
+ return memory_info.rss / (1024 * 1024) # type: ignore[no-any-return]
24
+
25
+
26
+ keys = [f"X-Any-{i}" for i in range(100)]
27
+ headers = {key: key * 2 for key in keys}
28
+
29
+
30
+ def check_for_leak() -> None:
31
+ trim_ram()
32
+ usage = get_memory_usage()
33
+ assert usage < 50, f"Memory leaked at: {usage} MB"
34
+
35
+
36
+ def _test_pop() -> None:
37
+ for _ in range(10):
38
+ for _ in range(100):
39
+ result = MultiDict(headers)
40
+ for k in keys:
41
+ result.pop(k)
42
+ check_for_leak()
43
+
44
+
45
+ def _test_popall() -> None:
46
+ for _ in range(10):
47
+ for _ in range(100):
48
+ result = MultiDict(headers)
49
+ for k in keys:
50
+ result.popall(k)
51
+ check_for_leak()
52
+
53
+
54
+ def _test_popone() -> None:
55
+ for _ in range(10):
56
+ for _ in range(100):
57
+ result = MultiDict(headers)
58
+ for k in keys:
59
+ result.popone(k)
60
+ check_for_leak()
61
+
62
+
63
+ def _test_del() -> None:
64
+ for _ in range(10):
65
+ for _ in range(100):
66
+ result = MultiDict(headers)
67
+ for k in keys:
68
+ del result[k]
69
+ check_for_leak()
70
+
71
+
72
+ def _run_isolated_case() -> None:
73
+ _test_pop()
74
+ _test_popall()
75
+ _test_popone()
76
+ _test_del()
77
+
78
+
79
+ if __name__ == "__main__":
80
+ _run_isolated_case()
@@ -15,6 +15,7 @@ IS_PYPY = platform.python_implementation() == "PyPy"
15
15
  "multidict_extend_multidict.py",
16
16
  "multidict_extend_tuple.py",
17
17
  "multidict_update_multidict.py",
18
+ "multidict_pop.py",
18
19
  ),
19
20
  )
20
21
  @pytest.mark.leaks
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes