summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2026-05-26 22:26:18 +0300
committerrobot-piglet <[email protected]>2026-05-26 22:58:12 +0300
commite7e308065735cdaf5dcb4348187dd43168e37d8e (patch)
tree7ca0f751b640460e979d1f8b032447e5147d5c16 /contrib/python
parent540c8c5d478736aed0a81bb7bf30da5aad866197 (diff)
Intermediate changes
commit_hash:4c139857684c7144eeea0ba5f8e53572276a86fc
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/hypothesis/py3/.dist-info/METADATA2
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py67
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/version.py2
-rw-r--r--contrib/python/hypothesis/py3/ya.make2
4 files changed, 70 insertions, 3 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA
index adb3b9f3fb3..4bb4b728a00 100644
--- a/contrib/python/hypothesis/py3/.dist-info/METADATA
+++ b/contrib/python/hypothesis/py3/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: hypothesis
-Version: 6.152.5
+Version: 6.152.6
Summary: The property-based testing library for Python
Author-email: "David R. MacIver and Zac Hatfield-Dodds" <[email protected]>
License-Expression: MPL-2.0
diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py
index 15a4c1bad61..5b283bb7515 100644
--- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py
+++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py
@@ -9,9 +9,11 @@
# obtain one at https://mozilla.org/MPL/2.0/.
import math
+import unicodedata
from collections import defaultdict
from collections.abc import Callable, Iterator, Sequence
from dataclasses import dataclass
+from functools import lru_cache
from typing import (
TYPE_CHECKING,
Any,
@@ -89,6 +91,34 @@ def sort_key(nodes: Sequence[ChoiceNode]) -> tuple[int, tuple[int, ...]]:
)
+@lru_cache(maxsize=4096)
+def _natural_simpler_chars(c, intervals):
+ """Return single-char replacements for ``c`` derived from natural text
+ transformations - case mapping (upper, lower, casefold) and unicode
+ decomposition (NFD, NFKD). We take each individual character of the
+ transformed form so that e.g. ``ß`` can shrink to ``s`` via casefold
+ even though the full case-folded form is two characters.
+
+ Only candidates which are in ``intervals`` and which have a strictly
+ smaller index in shrink order than ``c`` are returned, sorted by that
+ shrink-order index. Callers must pass a single character that is itself
+ in ``intervals``.
+ """
+ candidates: set[str] = set()
+ for form in ("NFKD", "NFD"):
+ candidates.update(unicodedata.normalize(form, c))
+ for transformed in (c.upper(), c.lower(), c.casefold()):
+ candidates.update(transformed)
+ candidates.discard(c)
+ original_idx = intervals.index_from_char_in_shrink_order(c)
+ result = sorted(
+ (intervals.index_from_char_in_shrink_order(cand), cand)
+ for cand in candidates
+ if cand in intervals
+ )
+ return [cand for idx, cand in result if idx < original_idx]
+
+
@dataclass(slots=True, frozen=False)
class ShrinkPass:
function: Any
@@ -321,6 +351,7 @@ class Shrinker:
ShrinkPass(self.redistribute_numeric_pairs),
ShrinkPass(self.lower_integers_together),
ShrinkPass(self.lower_duplicated_characters),
+ ShrinkPass(self.normalize_unicode_chars),
]
# Because the shrinker is also used to `pareto_optimise` in the target phase,
@@ -1549,6 +1580,42 @@ class Shrinker:
),
)
+ def normalize_unicode_chars(self, chooser):
+ """For string nodes, try replacing characters with simpler equivalents
+ from natural text transformations: unicode decomposition (NFD, NFKD)
+ and case mapping. For example, an accented latin letter is reduced
+ to its base form, a ligature is reduced to its first base character,
+ a mathematical alphanumeric symbol is reduced to its plain ascii
+ counterpart, and a lowercase letter is replaced with its uppercase
+ form (which has a smaller shrink-order index in the default
+ alphabet).
+
+ The codepoint shrinker is binary-search based, so it can get stuck on
+ a high codepoint whose simpler equivalents aren't reached by halving
+ / shifting / masking. This pass directly tries the natural simpler
+ forms one character at a time.
+ """
+ node = chooser.choose(
+ self.nodes,
+ lambda n: n.type == "string"
+ and any(
+ _natural_simpler_chars(c, n.constraints["intervals"]) for c in n.value
+ ),
+ )
+ intervals = node.constraints["intervals"]
+ i = chooser.choose(
+ range(len(node.value)),
+ lambda j: bool(_natural_simpler_chars(node.value[j], intervals)),
+ )
+ for replacement in _natural_simpler_chars(node.value[i], intervals):
+ new_value = node.value[:i] + replacement + node.value[i + 1 :]
+ if self.consider_new_nodes(
+ self.nodes[: node.index]
+ + (node.copy(with_value=new_value),)
+ + self.nodes[node.index + 1 :]
+ ):
+ return
+
def minimize_nodes(self, nodes):
choice_type = nodes[0].type
value = nodes[0].value
diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py
index bb420c28aea..5994b35ebfc 100644
--- a/contrib/python/hypothesis/py3/hypothesis/version.py
+++ b/contrib/python/hypothesis/py3/hypothesis/version.py
@@ -8,5 +8,5 @@
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.
-__version_info__ = (6, 152, 5)
+__version_info__ = (6, 152, 6)
__version__ = ".".join(map(str, __version_info__))
diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make
index 584f7300bd7..084316a1c7a 100644
--- a/contrib/python/hypothesis/py3/ya.make
+++ b/contrib/python/hypothesis/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(6.152.5)
+VERSION(6.152.6)
LICENSE(MPL-2.0)