Skip to content

Commit 0b4f04e

Browse files
Fix regression in filters.
The use of a `WeakValueDictionary` caused items to be removed from the cache. This is not a global anymore, so a normal dict should be fine.
1 parent 0e7b3e0 commit 0b4f04e

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

src/prompt_toolkit/filters/base.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import weakref
43
from abc import ABCMeta, abstractmethod
54
from typing import Callable, Dict, Iterable, List, Optional, Tuple, Union
65

@@ -16,12 +15,8 @@ class Filter(metaclass=ABCMeta):
1615
"""
1716

1817
def __init__(self) -> None:
19-
self._and_cache: weakref.WeakValueDictionary[
20-
Filter, _AndList
21-
] = weakref.WeakValueDictionary()
22-
self._or_cache: weakref.WeakValueDictionary[
23-
Filter, _OrList
24-
] = weakref.WeakValueDictionary()
18+
self._and_cache: dict[Filter, _AndList] = {}
19+
self._or_cache: dict[Filter, _OrList] = {}
2520
self._invert_result: Filter | None = None
2621

2722
@abstractmethod

tests/test_filter.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import pytest
4+
import gc
45

56
from prompt_toolkit.filters import Always, Condition, Filter, Never, to_filter
67

@@ -60,3 +61,25 @@ def test_to_filter():
6061

6162
with pytest.raises(TypeError):
6263
to_filter(4)
64+
65+
66+
def test_filter_cache_regression_1():
67+
# See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1729
68+
69+
cond = Condition(lambda: True)
70+
71+
# The use of a `WeakValueDictionary` caused this following expression to
72+
# fail. The problem is that the nested `(a & a)` expression gets garbage
73+
# collected between the two statements and is removed from our cache.
74+
x = (cond & cond) & cond
75+
y = (cond & cond) & cond
76+
assert x == y
77+
78+
def test_filter_cache_regression_2():
79+
cond1 = Condition(lambda: True)
80+
cond2 = Condition(lambda: True)
81+
cond3 = Condition(lambda: True)
82+
83+
x = (cond1 & cond2) & cond3
84+
y = (cond1 & cond2) & cond3
85+
assert x == y

0 commit comments

Comments
 (0)