Browse Source

Intermediate changes

robot-piglet 1 year ago
parent
commit
24ae9da923

+ 1 - 1
contrib/python/hypothesis/py3/.dist-info/METADATA

@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: hypothesis
-Version: 6.98.12
+Version: 6.98.13
 Summary: A library for property-based testing
 Home-page: https://hypothesis.works
 Author: David R. MacIver and Zac Hatfield-Dodds

+ 2 - 6
contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py

@@ -134,7 +134,7 @@ from hypothesis.strategies._internal.strategies import (
     one_of,
 )
 from hypothesis.strategies._internal.strings import (
-    FixedSizeBytes,
+    BytesStrategy,
     OneCharStringStrategy,
     TextStrategy,
 )
@@ -963,11 +963,7 @@ def binary(
     values.
     """
     check_valid_sizes(min_size, max_size)
-    if min_size == max_size:
-        return FixedSizeBytes(min_size)
-    return lists(
-        integers(min_value=0, max_value=255), min_size=min_size, max_size=max_size
-    ).map(bytes)
+    return BytesStrategy(min_size, max_size)
 
 
 @cacheable

+ 122 - 43
contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strings.py

@@ -11,14 +11,17 @@
 import copy
 import re
 import warnings
-from functools import lru_cache
+from functools import lru_cache, partial
 
 from hypothesis.errors import HypothesisWarning, InvalidArgument
 from hypothesis.internal import charmap
+from hypothesis.internal.filtering import max_len, min_len
 from hypothesis.internal.intervalsets import IntervalSet
 from hypothesis.strategies._internal.collections import ListStrategy
 from hypothesis.strategies._internal.lazy import unwrap_strategies
+from hypothesis.strategies._internal.numbers import IntegersStrategy
 from hypothesis.strategies._internal.strategies import SearchStrategy
+from hypothesis.vendor.pretty import pretty
 
 
 class OneCharStringStrategy(SearchStrategy):
@@ -76,6 +79,33 @@ class OneCharStringStrategy(SearchStrategy):
         return data.draw_string(self.intervals, min_size=1, max_size=1)
 
 
+_nonempty_names = (
+    "capitalize",
+    "expandtabs",
+    "join",
+    "lower",
+    "rsplit",
+    "split",
+    "splitlines",
+    "swapcase",
+    "title",
+    "upper",
+)
+_nonempty_and_content_names = (
+    "islower",
+    "isupper",
+    "isalnum",
+    "isalpha",
+    "isascii",
+    "isdigit",
+    "isspace",
+    "istitle",
+    "lstrip",
+    "rstrip",
+    "strip",
+)
+
+
 class TextStrategy(ListStrategy):
     def do_draw(self, data):
         # if our element strategy is OneCharStringStrategy, we can skip the
@@ -104,44 +134,17 @@ class TextStrategy(ListStrategy):
     _nonempty_filters = (
         *ListStrategy._nonempty_filters,
         str,
-        str.capitalize,
         str.casefold,
         str.encode,
-        str.expandtabs,
-        str.join,
-        str.lower,
-        str.rsplit,
-        str.split,
-        str.splitlines,
-        str.swapcase,
-        str.title,
-        str.upper,
+        *(getattr(str, n) for n in _nonempty_names),
     )
     _nonempty_and_content_filters = (
-        str.isidentifier,
-        str.islower,
-        str.isupper,
-        str.isalnum,
-        str.isalpha,
-        str.isascii,
         str.isdecimal,
-        str.isdigit,
         str.isnumeric,
-        str.isspace,
-        str.istitle,
-        str.lstrip,
-        str.rstrip,
-        str.strip,
+        *(getattr(str, n) for n in _nonempty_and_content_names),
     )
 
     def filter(self, condition):
-        if condition in (str.lower, str.title, str.upper):
-            warnings.warn(
-                f"You applied str.{condition.__name__} as a filter, but this allows "
-                f"all nonempty strings!  Did you mean str.is{condition.__name__}?",
-                HypothesisWarning,
-                stacklevel=2,
-            )
         elems = unwrap_strategies(self.element_strategy)
         if (
             condition is str.isidentifier
@@ -163,17 +166,76 @@ class TextStrategy(ListStrategy):
                 ),
                 # Filter to ensure that NFKC normalization keeps working in future
             ).filter(str.isidentifier)
+        if (new := _string_filter_rewrite(self, str, condition)) is not None:
+            return new
+        return super().filter(condition)
 
-        # We use ListStrategy filter logic for the conditions that *only* imply
-        # the string is nonempty.  Here, we increment the min_size but still apply
-        # the filter for conditions that imply nonempty *and specific contents*.
-        if condition in self._nonempty_and_content_filters:
-            assert self.max_size >= 1, "Always-empty is special cased in st.text()"
-            self = copy.copy(self)
-            self.min_size = max(1, self.min_size)
-            return ListStrategy.filter(self, condition)
 
-        return super().filter(condition)
+def _string_filter_rewrite(self, kind, condition):
+    if condition in (kind.lower, kind.title, kind.upper):
+        k = kind.__name__
+        warnings.warn(
+            f"You applied {k}.{condition.__name__} as a filter, but this allows "
+            f"all nonempty strings!  Did you mean {k}.is{condition.__name__}?",
+            HypothesisWarning,
+            stacklevel=2,
+        )
+
+    elems = unwrap_strategies(self.element_strategy)
+    if (
+        (kind is bytes or isinstance(elems, OneCharStringStrategy))
+        and isinstance(pattern := getattr(condition, "__self__", None), re.Pattern)
+        and isinstance(pattern.pattern, kind)
+    ):
+        from hypothesis.strategies._internal.regex import regex_strategy
+
+        print(f"{condition=}")
+        print(f"{condition.__name__=}")
+
+        if condition.__name__ == "match":
+            # Replace with an easier-to-handle equivalent condition
+            caret = "^" if kind is str else b"^"
+            pattern = re.compile(caret + pattern.pattern, flags=pattern.flags)
+            condition = pattern.search
+
+        if condition.__name__ in ("search", "findall", "fullmatch"):
+            s = regex_strategy(
+                pattern,
+                fullmatch=condition.__name__ == "fullmatch",
+                alphabet=self.element_strategy if kind is str else None,
+            )
+            if self.min_size > 0:
+                s = s.filter(partial(min_len, self.min_size))
+            if self.max_size < 1e999:
+                s = s.filter(partial(max_len, self.max_size))
+            return s
+        elif condition.__name__ in ("finditer", "scanner"):
+            # PyPy implements `finditer` as an alias to their `scanner` method
+            warnings.warn(
+                f"You applied {pretty(condition)} as a filter, but this allows "
+                f"any string at all!  Did you mean .findall ?",
+                HypothesisWarning,
+                stacklevel=3,
+            )
+            return self
+        elif condition.__name__ == "split":
+            warnings.warn(
+                f"You applied {pretty(condition)} as a filter, but this allows "
+                f"any nonempty string!  Did you mean .search ?",
+                HypothesisWarning,
+                stacklevel=3,
+            )
+            return self.filter(bool)
+
+    # We use ListStrategy filter logic for the conditions that *only* imply
+    # the string is nonempty.  Here, we increment the min_size but still apply
+    # the filter for conditions that imply nonempty *and specific contents*.
+    if condition in self._nonempty_and_content_filters and self.max_size >= 1:
+        self = copy.copy(self)
+        self.min_size = max(1, self.min_size)
+        return ListStrategy.filter(self, condition)
+
+    return None
 
 
 # Excerpted from https://www.unicode.org/Public/15.0.0/ucd/PropList.txt
@@ -229,9 +291,26 @@ def _identifier_characters():
     return id_start, id_continue
 
 
-class FixedSizeBytes(SearchStrategy):
-    def __init__(self, size):
-        self.size = size
+class BytesStrategy(ListStrategy):
+    def __init__(self, min_size, max_size):
+        super().__init__(IntegersStrategy(0, 255), min_size=min_size, max_size=max_size)
 
     def do_draw(self, data):
-        return bytes(data.draw_bytes(self.size))
+        # TODO: refactor the underlying provider to support variable-length bytes
+        if self.min_size == self.max_size:
+            return bytes(data.draw_bytes(self.min_size))
+        return bytes(super().do_draw(data))
+
+    _nonempty_filters = (
+        *ListStrategy._nonempty_filters,
+        bytes,
+        *(getattr(bytes, n) for n in _nonempty_names),
+    )
+    _nonempty_and_content_filters = (
+        *(getattr(bytes, n) for n in _nonempty_and_content_names),
+    )
+
+    def filter(self, condition):
+        if (new := _string_filter_rewrite(self, bytes, condition)) is not None:
+            return new
+        return super().filter(condition)

+ 1 - 1
contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py

@@ -747,7 +747,7 @@ _type_pprinters = {
     type: _type_pprint,
     types.FunctionType: _function_pprint,
     types.BuiltinFunctionType: _function_pprint,
-    types.MethodType: _repr_pprint,
+    types.MethodType: _function_pprint,
     datetime.datetime: _repr_pprint,
     datetime.timedelta: _repr_pprint,
     BaseException: _exception_pprint,

+ 1 - 1
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, 98, 12)
+__version_info__ = (6, 98, 13)
 __version__ = ".".join(map(str, __version_info__))

+ 1 - 1
contrib/python/hypothesis/py3/ya.make

@@ -2,7 +2,7 @@
 
 PY3_LIBRARY()
 
-VERSION(6.98.12)
+VERSION(6.98.13)
 
 LICENSE(MPL-2.0)
 

+ 0 - 1
yt/yt/library/formats/skiff_yson_converter.cpp

@@ -1420,7 +1420,6 @@ TSkiffToYsonConverter CreateSimpleSkiffToYsonConverter(
             case ESimpleLogicalValueType::Interval64:
                 CheckWireType(wireType, {EWireType::Int32, EWireType::Int64, EWireType::String32});
                 return CreatePrimitiveTypeSkiffToYsonConverter(wireType);
-
         }
         YT_ABORT();
     } catch (const std::exception& ex) {