diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-19 10:27:19 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-19 10:36:59 +0300 |
commit | 8cd355bb423ef1b67f07b50276100dadc92a1f2c (patch) | |
tree | 6ebab06b5f5ccb6965e3475f568ea500c1e1c746 /contrib/python | |
parent | 775af717c30bba818ca2bc47adae5ae199fcda03 (diff) | |
download | ydb-8cd355bb423ef1b67f07b50276100dadc92a1f2c.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python')
9 files changed, 108 insertions, 36 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index f836949548..557900da69 100644 --- a/contrib/python/hypothesis/py3/.dist-info/METADATA +++ b/contrib/python/hypothesis/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: hypothesis -Version: 6.108.5 +Version: 6.108.8 Summary: A library for property-based testing Home-page: https://hypothesis.works Author: David R. MacIver and Zac Hatfield-Dodds @@ -41,10 +41,10 @@ Requires-Dist: exceptiongroup >=1.0.0 ; python_version < "3.11" Provides-Extra: all Requires-Dist: black >=19.10b0 ; extra == 'all' Requires-Dist: click >=7.0 ; extra == 'all' -Requires-Dist: crosshair-tool >=0.0.63 ; extra == 'all' +Requires-Dist: crosshair-tool >=0.0.65 ; extra == 'all' Requires-Dist: django >=3.2 ; extra == 'all' Requires-Dist: dpcontracts >=0.4 ; extra == 'all' -Requires-Dist: hypothesis-crosshair >=0.0.9 ; extra == 'all' +Requires-Dist: hypothesis-crosshair >=0.0.11 ; extra == 'all' Requires-Dist: lark >=0.10.1 ; extra == 'all' Requires-Dist: libcst >=0.3.16 ; extra == 'all' Requires-Dist: numpy >=1.17.3 ; extra == 'all' @@ -63,8 +63,8 @@ Requires-Dist: rich >=9.0.0 ; extra == 'cli' Provides-Extra: codemods Requires-Dist: libcst >=0.3.16 ; extra == 'codemods' Provides-Extra: crosshair -Requires-Dist: hypothesis-crosshair >=0.0.9 ; extra == 'crosshair' -Requires-Dist: crosshair-tool >=0.0.63 ; extra == 'crosshair' +Requires-Dist: hypothesis-crosshair >=0.0.11 ; extra == 'crosshair' +Requires-Dist: crosshair-tool >=0.0.65 ; extra == 'crosshair' Provides-Extra: dateutil Requires-Dist: python-dateutil >=1.4 ; extra == 'dateutil' Provides-Extra: django diff --git a/contrib/python/hypothesis/py3/hypothesis/control.py b/contrib/python/hypothesis/py3/hypothesis/control.py index 69ccf19ef2..f36ceb676b 100644 --- a/contrib/python/hypothesis/py3/hypothesis/control.py +++ b/contrib/python/hypothesis/py3/hypothesis/control.py @@ -139,10 +139,9 @@ class BuildContext: self.known_object_printers = defaultdict(list) def record_call(self, obj, func, args, kwargs): - name = get_pretty_function_description(func) self.known_object_printers[IDKey(obj)].append( - lambda obj, p, cycle: p.maybe_repr_known_object_as_call( - obj, cycle, name, args, kwargs + lambda obj, p, cycle, *, _func=func: p.maybe_repr_known_object_as_call( + obj, cycle, get_pretty_function_description(_func), args, kwargs ) ) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py index 49c1956867..a41cdb0549 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py @@ -9,6 +9,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. import threading +from collections import OrderedDict import attr @@ -282,3 +283,64 @@ class LRUReusedCache(GenericCache): def on_access(self, key, value, score): return (2, self.tick()) + + +class LRUCache: + """ + This is a drop-in replacement for a GenericCache (despite the lack of inheritance) + in performance critical environments. It turns out that GenericCache's heap + balancing for arbitrary scores can be quite expensive compared to the doubly + linked list approach of lru_cache or OrderedDict. + + This class is a pure LRU and does not provide any sort of affininty towards + the number of accesses beyond recency. If soft-pinning entries which have been + accessed at least once is important, use LRUReusedCache. + """ + + # Here are some nice performance references for lru_cache vs OrderedDict: + # https://github.com/python/cpython/issues/72426#issuecomment-1093727671 + # https://discuss.python.org/t/simplify-lru-cache/18192/6 + # + # We use OrderedDict here because it is unclear to me we can provide the same + # api as GenericCache without messing with @lru_cache internals. + # + # Anecdotally, OrderedDict seems quite competitive with lru_cache, but perhaps + # that is localized to our access patterns. + + def __init__(self, max_size): + assert max_size > 0 + self.max_size = max_size + self._threadlocal = threading.local() + + @property + def cache(self): + try: + return self._threadlocal.cache + except AttributeError: + self._threadlocal.cache = OrderedDict() + return self._threadlocal.cache + + def __setitem__(self, key, value): + self.cache[key] = value + self.cache.move_to_end(key) + + while len(self.cache) > self.max_size: + self.cache.popitem(last=False) + + def __getitem__(self, key): + val = self.cache[key] + self.cache.move_to_end(key) + return val + + def __iter__(self): + return iter(self.cache) + + def __len__(self): + return len(self.cache) + + def __contains__(self, key): + return key in self.cache + + # implement GenericCache interface, for tests + def check_valid(self): + pass diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index 3f81f262eb..785eb92328 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -41,7 +41,7 @@ from typing import ( import attr from hypothesis.errors import Frozen, InvalidArgument, StopTest -from hypothesis.internal.cache import LRUReusedCache +from hypothesis.internal.cache import LRUCache from hypothesis.internal.compat import add_note, floor, int_from_bytes, int_to_bytes from hypothesis.internal.conjecture.floats import float_to_lex, lex_to_float from hypothesis.internal.conjecture.junkdrawer import ( @@ -200,9 +200,11 @@ NASTY_FLOATS = sorted( NASTY_FLOATS = list(map(float, NASTY_FLOATS)) NASTY_FLOATS.extend([-x for x in NASTY_FLOATS]) -FLOAT_INIT_LOGIC_CACHE = LRUReusedCache(4096) - -POOLED_KWARGS_CACHE = LRUReusedCache(4096) +# These caches, especially the kwargs cache, can be quite hot and so we prefer +# LRUCache over LRUReusedCache for performance. We lose scan resistance, but +# that's probably fine here. +FLOAT_INIT_LOGIC_CACHE = LRUCache(4096) +POOLED_KWARGS_CACHE = LRUCache(4096) DRAW_STRING_DEFAULT_MAX_SIZE = 10**10 # "arbitrarily large" diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py index 572679d403..f7e7dbc272 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py @@ -59,6 +59,7 @@ from hypothesis.control import ( current_build_context, deprecate_random_in_strategy, note, + should_note, ) from hypothesis.errors import ( HypothesisSideeffectWarning, @@ -2115,9 +2116,11 @@ class DataObject: if TESTCASE_CALLBACKS: self.conjecture_data._observability_args[desc] = to_jsonable(result) - printer.text(desc) - printer.pretty(result) - note(printer.getvalue()) + # optimization to avoid needless printer.pretty + if should_note(): + printer.text(desc) + printer.pretty(result) + note(printer.getvalue()) return result diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/functions.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/functions.py index 9eb6fcb755..cf4d6275f8 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/functions.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/functions.py @@ -10,7 +10,7 @@ from weakref import WeakKeyDictionary -from hypothesis.control import note +from hypothesis.control import note, should_note from hypothesis.errors import InvalidState from hypothesis.internal.reflection import ( convert_positional_arguments, @@ -50,13 +50,15 @@ class FunctionStrategy(SearchStrategy): cache = self._cache.setdefault(inner, {}) if key not in cache: cache[key] = data.draw(self.returns) - rep = repr_call(self.like, args, kwargs, reorder=False) - note(f"Called function: {rep} -> {cache[key]!r}") + if should_note(): # optimization to avoid needless repr_call + rep = repr_call(self.like, args, kwargs, reorder=False) + note(f"Called function: {rep} -> {cache[key]!r}") return cache[key] else: val = data.draw(self.returns) - rep = repr_call(self.like, args, kwargs, reorder=False) - note(f"Called function: {rep} -> {val!r}") + if should_note(): + rep = repr_call(self.like, args, kwargs, reorder=False) + note(f"Called function: {rep} -> {val!r}") return val return inner diff --git a/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py b/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py index 6b4718ff79..9c092de367 100644 --- a/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py +++ b/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py @@ -143,8 +143,6 @@ class RepresentationPrinter: self.group_queue = GroupQueue(root_group) self.indentation = 0 - self.snans = 0 - self.stack = [] self.singleton_pprinters = {} self.type_pprinters = {} @@ -358,12 +356,6 @@ class RepresentationPrinter: def flush(self): """Flush data that is left in the buffer.""" - if self.snans: - # Reset self.snans *before* calling breakable(), which might flush() - snans = self.snans - self.snans = 0 - self.breakable(" ") - self.text(f"# Saw {snans} signaling NaN" + "s" * (snans > 1)) for data in self.buffer: self.output_width += data.output(self.output, self.output_width) self.buffer.clear() @@ -747,19 +739,31 @@ def _exception_pprint(obj, p, cycle): p.pretty(arg) +def _repr_integer(obj, p, cycle): + if abs(obj) < 1_000_000_000: + p.text(repr(obj)) + elif abs(obj) < 10**640: + # add underscores for integers over ten decimal digits + p.text(f"{obj:#_d}") + else: + # for very very large integers, use hex because power-of-two bases are cheaper + # https://docs.python.org/3/library/stdtypes.html#integer-string-conversion-length-limitation + p.text(f"{obj:#_x}") + + def _repr_float_counting_nans(obj, p, cycle): - if isnan(obj) and hasattr(p, "snans"): + if isnan(obj): if struct.pack("!d", abs(obj)) != struct.pack("!d", float("nan")): - p.snans += 1 - if copysign(1.0, obj) == -1.0: - p.text("-nan") - return + show = hex(*struct.unpack("Q", struct.pack("d", obj))) + return p.text(f"struct.unpack('d', struct.pack('Q', {show}))[0]") + elif copysign(1.0, obj) == -1.0: + return p.text("-nan") p.text(repr(obj)) #: printers for builtin types _type_pprinters = { - int: _repr_pprint, + int: _repr_integer, float: _repr_float_counting_nans, str: _repr_pprint, tuple: _seq_pprinter_factory("(", ")", tuple), diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 7a526dd733..f800a2e0aa 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, 108, 5) +__version_info__ = (6, 108, 8) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index 172daf15d1..65d6b4d769 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.108.5) +VERSION(6.108.8) LICENSE(MPL-2.0) |