Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-hypothesis for openSUSE:Factory checked in at 2023-01-10 14:58:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-hypothesis (Old) and /work/SRC/openSUSE:Factory/.python-hypothesis.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-hypothesis" Tue Jan 10 14:58:58 2023 rev:62 rq:1056961 version:6.61.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-hypothesis/python-hypothesis.changes 2023-01-06 17:05:03.816015554 +0100 +++ /work/SRC/openSUSE:Factory/.python-hypothesis.new.32243/python-hypothesis.changes 2023-01-10 14:59:00.864950720 +0100 @@ -1,0 +2,17 @@ +Sat Jan 7 21:27:40 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 6.61.2 + * This patch improves our pretty-printing of failing examples, + including some refactoring to prepare for exciting future + features. +- Release 6.61.1 + * This patch brings our domains() and emails() strategies into + compliance with RFC 5890 §2.3.1: we no longer generate + parts-of-domains where the third and fourth characters are -- + (âR-LDH labelsâ), though future versions may deliberately + generate xn-- punycode labels. Thanks to python-email-validator + for the report! +- Update dependencies +- Move to PEP517 build + +------------------------------------------------------------------- Old: ---- hypothesis-python-6.61.0.tar.gz New: ---- hypothesis-python-6.61.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-hypothesis.spec ++++++ --- /var/tmp/diff_new_pack.7yuO22/_old 2023-01-10 14:59:02.776960955 +0100 +++ /var/tmp/diff_new_pack.7yuO22/_new 2023-01-10 14:59:02.780960976 +0100 @@ -1,7 +1,7 @@ # # spec file # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -31,7 +31,7 @@ %bcond_with test %endif Name: python-hypothesis%{psuffix} -Version: 6.61.0 +Version: 6.61.2 Release: 0 Summary: A library for property based testing License: MPL-2.0 @@ -41,24 +41,26 @@ # See also https://hypothesis.readthedocs.io/en/latest/packaging.html Source: hypothesis-python-%{version}.tar.gz BuildRequires: %{python_module base >= 3.7} +BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-attrs >= 19.2.0 -Requires: python-exceptiongroup >= 1.0.0 -Requires: python-sortedcontainers >= 2.1.0 +Requires: (python-exceptiongroup >= 1.0.0 if python-base < 3.11) +Requires: (python-sortedcontainers >= 2.1.0 with python-sortedcontainers < 3.0) Requires(post): update-alternatives Requires(preun):update-alternatives # SECTION requires_extra # consuming packages need to declare these optional dependencies explicitly -Recommends: python-Django >= 2.2 +Recommends: python-Django >= 3.2 Recommends: python-black >= 19.10 Recommends: python-click >= 7.0 Recommends: python-dpcontracts >= 0.4 Recommends: python-lark >= 0.10.1 Recommends: python-libcst >= 0.3.16 Recommends: python-numpy >= 1.9.0 -Recommends: python-pandas >= 0.25 +Recommends: python-pandas >= 1.0 Recommends: python-pytest >= 4.6 Recommends: python-python-dateutil >= 1.4 Recommends: python-pytz >= 2014.1 @@ -68,16 +70,14 @@ # /SECTION BuildArch: noarch %if %{with test} -BuildRequires: %{python_module attrs >= 19.2.0} -BuildRequires: %{python_module sortedcontainers >= 2.1.0} +BuildRequires: %{python_module hypothesis = %{version}} # SECTION test requirements -BuildRequires: %{python_module Django >= 2.2} +BuildRequires: %{python_module Django >= 3.2} BuildRequires: %{python_module backports.zoneinfo >= 0.2.1 if %python-base < 3.9} BuildRequires: %{python_module black >= 19.10} BuildRequires: %{python_module dpcontracts >= 0.4} BuildRequires: %{python_module fakeredis} BuildRequires: %{python_module flaky} -BuildRequires: %{python_module hypothesis = %{version}} BuildRequires: %{python_module lark >= 0.10.1} BuildRequires: %{python_module libcst >= 0.3.16} BuildRequires: %{python_module numpy >= 1.9.0} @@ -113,12 +113,12 @@ %build %if !%{with test} -%python_build +%pyproject_wheel %endif %install %if !%{with test} -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %python_clone -a %{buildroot}%{_bindir}/hypothesis @@ -170,7 +170,7 @@ %doc README.rst %python_alternative %{_bindir}/hypothesis %{python_sitelib}/*hypothesis* -%{python_sitelib}/hypothesis-%{version}-py*.egg-info +%{python_sitelib}/hypothesis-%{version}.dist-info %pycache_only %{python_sitelib}/__pycache__/*hypothesis* %endif ++++++ _service ++++++ --- /var/tmp/diff_new_pack.7yuO22/_old 2023-01-10 14:59:02.836961276 +0100 +++ /var/tmp/diff_new_pack.7yuO22/_new 2023-01-10 14:59:02.840961297 +0100 @@ -2,7 +2,7 @@ <service name="tar_scm" mode="disabled"> <param name="url">https://github.com/HypothesisWorks/hypothesis.git</param> <param name="scm">git</param> - <param name="revision">hypothesis-python-6.61.0</param> + <param name="revision">hypothesis-python-6.61.2</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">hypothesis-python-(.*)</param> <param name="subdir">hypothesis-python</param> ++++++ hypothesis-python-6.61.0.tar.gz -> hypothesis-python-6.61.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/docs/changes.rst new/hypothesis-python-6.61.2/docs/changes.rst --- old/hypothesis-python-6.61.0/docs/changes.rst 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/docs/changes.rst 2023-01-07 11:48:18.000000000 +0100 @@ -18,6 +18,29 @@ .. include:: ../RELEASE.rst +.. _v6.61.2: + +------------------- +6.61.2 - 2023-01-07 +------------------- + +This patch improves our pretty-printing of failing examples, including +some refactoring to prepare for exciting future features. + +.. _v6.61.1: + +------------------- +6.61.1 - 2023-01-06 +------------------- + +This patch brings our :func:`~hypothesis.provisional.domains` and +:func:`~hypothesis.strategies.emails` strategies into compliance with +:rfc:`RFC 5890 §2.3.1 <5890>`: we no longer generate parts-of-domains +where the third and fourth characters are ``--`` ("R-LDH labels"), +though future versions *may* deliberately generate ``xn--`` punycode +labels. Thanks to :pypi:`python-email-validator` for `the report +<https://github.com/JoshData/python-email-validator/issues/92>`__! + .. _v6.61.0: ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/_error_if_old.py new/hypothesis-python-6.61.2/src/hypothesis/_error_if_old.py --- old/hypothesis-python-6.61.0/src/hypothesis/_error_if_old.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/_error_if_old.py 2023-01-07 11:48:18.000000000 +0100 @@ -19,5 +19,5 @@ See https://packaging.python.org/guides/distributing-packages-using-setuptools/ """ -if sys.version_info[:2] < (3, 7): # pragma: no cover +if sys.version_info[:2] < (3, 7): raise Exception(message.format(__version__)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/control.py new/hypothesis-python-6.61.2/src/hypothesis/control.py --- old/hypothesis-python-6.61.0/src/hypothesis/control.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/control.py 2023-01-07 11:48:18.000000000 +0100 @@ -9,7 +9,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. import math -from typing import NoReturn, Union +from typing import NoReturn, Optional, Union from hypothesis import Verbosity, settings from hypothesis.errors import InvalidArgument, UnsatisfiedAssumption @@ -51,7 +51,7 @@ return _current_build_context.value is not None -def current_build_context(): +def current_build_context() -> "Optional[BuildContext]": context = _current_build_context.value if context is None: raise InvalidArgument("No build context registered") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/core.py new/hypothesis-python-6.61.2/src/hypothesis/core.py --- old/hypothesis-python-6.61.0/src/hypothesis/core.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/core.py 2023-01-07 11:48:18.000000000 +0100 @@ -196,7 +196,7 @@ # This is deliberately a no-op at runtime; the tools operate on source code. return self - if sys.version_info[:2] >= (3, 8): # pragma: no branch + if sys.version_info[:2] >= (3, 8): # We want a positional-only argument, and on Python 3.8+ we'll get it. __sig = get_signature(via) via = define_function_signature( @@ -348,7 +348,7 @@ if ... in given_arguments: return invalid( - "... was passed as a positional argument to @given, but may only be " + "... was passed as a positional argument to @given, but may only be " "passed as a keyword argument or as the sole argument of @given" ) @@ -717,28 +717,13 @@ if self.print_given_args: printer.text(" ") - printer.text(test.__name__) - with printer.group(indent=4, open="(", close=""): - printer.break_() - for v in args: - printer.pretty(v) - # We add a comma unconditionally because - # generated arguments will always be kwargs, - # so there will always be more to come. - printer.text(",") - printer.breakable() - - for i, (k, v) in enumerate(kwargs.items()): - printer.text(k) - printer.text("=") - printer.pretty(v) - printer.text(",") - if i + 1 < len(kwargs): - printer.breakable() - printer.break_() - printer.text(")") - printer.flush() - report(output.getvalue()) + printer.repr_call( + test.__name__, + args, + kwargs, + force_split=True, + ) + report(printer.getvalue()) return test(*args, **kwargs) # Run the test function once, via the executor hook. @@ -1119,7 +1104,7 @@ for p in original_sig.parameters.values() if p.kind is p.POSITIONAL_OR_KEYWORD ] - given_kwargs = dict(zip(posargs[::-1], given_arguments[::-1])) + given_kwargs = dict(list(zip(posargs[::-1], given_arguments[::-1]))[::-1]) # These have been converted, so delete them to prevent accidental use. del given_arguments diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/extra/django/_impl.py new/hypothesis-python-6.61.2/src/hypothesis/extra/django/_impl.py --- old/hypothesis-python-6.61.0/src/hypothesis/extra/django/_impl.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/extra/django/_impl.py 2023-01-07 11:48:18.000000000 +0100 @@ -25,7 +25,7 @@ from hypothesis.internal.reflection import define_function_signature from hypothesis.strategies._internal.utils import defines_strategy -if sys.version_info >= (3, 10): # pragma: no cover +if sys.version_info >= (3, 10): from types import EllipsisType as EllipsisType elif TYPE_CHECKING: from builtins import ellipsis as EllipsisType @@ -130,7 +130,7 @@ return _models_impl(st.builds(m_type.objects.get_or_create, **field_strategies)) -if sys.version_info[:2] >= (3, 8): # pragma: no branch +if sys.version_info[:2] >= (3, 8): # See notes above definition of st.builds() - this signature is compatible # and better matches the semantics of the function. Great for documentation! sig = signature(from_model) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/extra/numpy.py new/hypothesis-python-6.61.2/src/hypothesis/extra/numpy.py --- old/hypothesis-python-6.61.0/src/hypothesis/extra/numpy.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/extra/numpy.py 2023-01-07 11:48:18.000000000 +0100 @@ -208,15 +208,18 @@ ) from err if elem_changed: strategy = self.fill if fill else self.element_strategy - if self.dtype.kind == "f": + if self.dtype.kind == "f": # pragma: no cover + # This logic doesn't trigger in our coverage tests under Numpy 1.24+, + # with built-in checks for overflow, but we keep it for good error + # messages and compatibility with older versions of Numpy. try: is_subnormal = 0 < abs(val) < np.finfo(self.dtype).tiny - except Exception: # pragma: no cover + except Exception: # val may be a non-float that does not support the # operations __lt__ and __abs__ - is_subnormal = False # pragma: no cover + is_subnormal = False if is_subnormal: - raise InvalidArgument( # pragma: no cover + raise InvalidArgument( f"Generated subnormal float {val} from strategy " f"{strategy} resulted in {result[idx]!r}, probably " "as a result of NumPy being built with flush-to-zero " diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/internal/entropy.py new/hypothesis-python-6.61.2/src/hypothesis/internal/entropy.py --- old/hypothesis-python-6.61.0/src/hypothesis/internal/entropy.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/internal/entropy.py 2023-01-07 11:48:18.000000000 +0100 @@ -22,7 +22,7 @@ from hypothesis.internal.compat import PYPY if TYPE_CHECKING: - if sys.version_info >= (3, 8): # pragma: no cover + if sys.version_info >= (3, 8): from typing import Protocol else: from typing_extensions import Protocol diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/internal/reflection.py new/hypothesis-python-6.61.2/src/hypothesis/internal/reflection.py --- old/hypothesis-python-6.61.0/src/hypothesis/internal/reflection.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/internal/reflection.py 2023-01-07 11:48:18.000000000 +0100 @@ -443,6 +443,7 @@ def repr_call(f, args, kwargs, reorder=True): + # Note: for multi-line pretty-printing, see RepresentationPrinter.repr_call() if reorder: args, kwargs = convert_positional_arguments(f, args, kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/provisional.py new/hypothesis-python-6.61.2/src/hypothesis/provisional.py --- old/hypothesis-python-6.61.0/src/hypothesis/provisional.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/provisional.py 2023-01-07 11:48:18.000000000 +0100 @@ -107,6 +107,11 @@ ).map("".join) ) ) + # RFC-5890 s2.3.1 says such labels are reserved, and since we don't + # want to bother with xn-- punycode labels we'll exclude them all. + elem_st = st.from_regex(self.label_regex, fullmatch=True).filter( + lambda label: len(label) < 4 or label[2:4] != "--" + ) # The maximum possible number of subdomains is 126, # 1 character subdomain + 1 '.' character, * 126 = 252, # with a max of 255, that leaves 3 characters for a TLD. @@ -115,7 +120,7 @@ elements = cu.many(data, min_size=1, average_size=3, max_size=126) while elements.more(): # Generate a new valid subdomain using the regex strategy. - sub_domain = data.draw(st.from_regex(self.label_regex, fullmatch=True)) + sub_domain = data.draw(elem_st) if len(domain) + len(sub_domain) >= self.max_length: data.stop_example(discard=True) break diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/core.py new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/core.py --- old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/core.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/core.py 2023-01-07 11:48:18.000000000 +0100 @@ -116,6 +116,7 @@ ) from hypothesis.strategies._internal.utils import cacheable, defines_strategy from hypothesis.utils.conventions import not_set +from hypothesis.vendor.pretty import RepresentationPrinter if sys.version_info >= (3, 10): from types import EllipsisType as EllipsisType @@ -125,7 +126,7 @@ EllipsisType = type(Ellipsis) # pragma: no cover -if sys.version_info >= (3, 8): # pragma: no cover +if sys.version_info >= (3, 8): from typing import Protocol elif TYPE_CHECKING: from typing_extensions import Protocol @@ -902,7 +903,7 @@ If the callable is a class defined with :pypi:`attrs`, missing required arguments will be inferred from the attribute on a best-effort basis, - e.g. by checking :ref:`attrs standard validators <attrs:api_validators>`. + e.g. by checking :ref:`attrs standard validators <attrs:api-validators>`. Dataclasses are handled natively by the inference from type hints. Examples from this strategy shrink by shrinking the argument values to @@ -960,7 +961,7 @@ return BuildsStrategy(target, args, kwargs) -if sys.version_info[:2] >= (3, 8): # pragma: no branch +if sys.version_info[:2] >= (3, 8): # See notes above definition - this signature is compatible and better # matches the semantics of the function. Great for documentation! sig = signature(builds) @@ -1834,10 +1835,11 @@ check_strategy(strategy, "strategy") result = self.conjecture_data.draw(strategy) self.count += 1 - if label is not None: - note(f"Draw {self.count} ({label}): {result!r}") - else: - note(f"Draw {self.count}: {result!r}") + printer = RepresentationPrinter() + printer.text(f"Draw {self.count}") + printer.text(": " if label is None else f" ({label}): ") + printer.pretty(result) + note(printer.getvalue()) return result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/random.py new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/random.py --- old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/random.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/random.py 2023-01-07 11:48:18.000000000 +0100 @@ -70,6 +70,7 @@ for name in [ "_randbelow", "betavariate", + "binomialvariate", "choice", "choices", "expovariate", @@ -271,6 +272,9 @@ result = cu.integer_range(self.__data, start, stop - 1) elif method == "randint": result = cu.integer_range(self.__data, kwargs["a"], kwargs["b"]) + # New in Python 3.12, so not taken by our coverage job + elif method == "binomialvariate": # pragma: no cover + result = cu.integer_range(self.__data, 0, kwargs["n"]) elif method == "choice": seq = kwargs["seq"] result = cu.integer_range(self.__data, 0, len(seq) - 1) @@ -317,8 +321,7 @@ result = self.__data.draw(floats(min_value=0.0)) elif method == "shuffle": result = self.__data.draw(permutations(range(len(kwargs["x"])))) - # This is tested for but only appears in 3.9 so doesn't appear in coverage. - elif method == "randbytes": # pragma: no cover + elif method == "randbytes": n = kwargs["n"] result = self.__data.draw(binary(min_size=n, max_size=n)) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/types.py new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/types.py --- old/hypothesis-python-6.61.0/src/hypothesis/strategies/_internal/types.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/strategies/_internal/types.py 2023-01-07 11:48:18.000000000 +0100 @@ -582,7 +582,7 @@ _global_type_lookup[type] = st.sampled_from( [type(None)] + sorted(_global_type_lookup, key=str) ) -if sys.version_info[:2] >= (3, 9): # pragma: no cover +if sys.version_info[:2] >= (3, 9): # subclass of MutableMapping, and in Python 3.9 we resolve to a union # which includes this... but we don't actually ever want to build one. _global_type_lookup[os._Environ] = st.just(os.environ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/vendor/pretty.py new/hypothesis-python-6.61.2/src/hypothesis/vendor/pretty.py --- old/hypothesis-python-6.61.0/src/hypothesis/vendor/pretty.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/vendor/pretty.py 2023-01-07 11:48:18.000000000 +0100 @@ -63,7 +63,6 @@ """ import datetime -import platform import re import struct import types @@ -74,17 +73,12 @@ __all__ = [ "pretty", - "PrettyPrinter", "RepresentationPrinter", - "for_type_by_name", ] -MAX_SEQ_LENGTH = 1000 _re_pattern_type = type(re.compile("")) -PYPY = platform.python_implementation() == "PyPy" - def _safe_getattr(obj, attr, default=None): """Safe version of getattr. @@ -99,56 +93,28 @@ return default -def pretty( - obj, verbose=False, max_width=79, newline="\n", max_seq_length=MAX_SEQ_LENGTH -): +def pretty(obj): """Pretty print the object's representation.""" - stream = StringIO() - printer = RepresentationPrinter( - stream, verbose, max_width, newline, max_seq_length=max_seq_length - ) + printer = RepresentationPrinter() printer.pretty(obj) - printer.flush() - return stream.getvalue() - - -class _PrettyPrinterBase: - @contextmanager - def indent(self, indent): - """`with`-statement support for indenting/dedenting.""" - self.indentation += indent - try: - yield - finally: - self.indentation -= indent + return printer.getvalue() - @contextmanager - def group(self, indent=0, open="", close=""): - """Like begin_group / end_group but for the with statement.""" - self.begin_group(indent, open) - try: - yield - finally: - self.end_group(indent, close) +class RepresentationPrinter: + """Special pretty printer that has a `pretty` method that calls the pretty + printer for a python object. -class PrettyPrinter(_PrettyPrinterBase): - """Baseclass for the `RepresentationPrinter` prettyprinter that is used to - generate pretty reprs of objects. - - Contrary to the `RepresentationPrinter` this printer knows nothing - about the default pprinters or the `_repr_pretty_` callback method. + This class stores processing data on `self` so you must *never* use + this class in a threaded environment. Always lock it or + reinstantiate it. """ - def __init__( - self, output, max_width=79, newline="\n", max_seq_length=MAX_SEQ_LENGTH - ): + def __init__(self, output=None): self.broken = False - self.output = output - self.max_width = max_width - self.newline = newline - self.max_seq_length = max_seq_length + self.output = StringIO() if output is None else output + self.max_width = 79 + self.max_seq_length = 1000 self.output_width = 0 self.buffer_width = 0 self.buffer = deque() @@ -160,6 +126,59 @@ self.snans = 0 + self.stack = [] + self.singleton_pprinters = _singleton_pprinters.copy() + self.type_pprinters = _type_pprinters.copy() + self.deferred_pprinters = _deferred_type_pprinters.copy() + + def pretty(self, obj): + """Pretty print the given object.""" + obj_id = id(obj) + cycle = obj_id in self.stack + self.stack.append(obj_id) + try: + with self.group(): + obj_class = _safe_getattr(obj, "__class__", None) or type(obj) + # First try to find registered singleton printers for the type. + try: + printer = self.singleton_pprinters[obj_id] + except (TypeError, KeyError): + pass + else: + return printer(obj, self, cycle) + # Next walk the mro and check for either: + # 1) a registered printer + # 2) a _repr_pretty_ method + for cls in obj_class.__mro__: + if cls in self.type_pprinters: + # printer registered in self.type_pprinters + return self.type_pprinters[cls](obj, self, cycle) + else: + # Check if the given class is specified in the deferred type + # registry; move it to the regular type registry if so. + key = ( + _safe_getattr(cls, "__module__", None), + _safe_getattr(cls, "__name__", None), + ) + if key in self.deferred_pprinters: + # Move the printer over to the regular registry. + printer = self.deferred_pprinters.pop(key) + self.type_pprinters[cls] = printer + return printer(obj, self, cycle) + else: + # Finally look for special method names. + # Some objects automatically create any requested + # attribute. Try to ignore most of them by checking for + # callability. + if "_repr_pretty_" in cls.__dict__: + meth = cls._repr_pretty_ + if callable(meth): + return meth(obj, self, cycle) + # A user-provided repr. Find newlines and replace them with p.break_() + return _repr_pprint(obj, self, cycle) + finally: + self.stack.pop() + def _break_outer_groups(self): while self.max_width < self.output_width + self.buffer_width: group = self.group_queue.deq() @@ -201,8 +220,7 @@ group = self.group_stack[-1] if group.want_break: self.flush() - self.output.write(self.newline) - self.output.write(" " * self.indentation) + self.output.write("\n" + " " * self.indentation) self.output_width = self.indentation self.buffer_width = 0 else: @@ -214,24 +232,28 @@ """Explicitly insert a newline into the output, maintaining correct indentation.""" self.flush() - self.output.write(self.newline) - self.output.write(" " * self.indentation) + self.output.write("\n" + " " * self.indentation) self.output_width = self.indentation self.buffer_width = 0 - def begin_group(self, indent=0, open=""): - """ - Begin a group. If you want support for python < 2.5 which doesn't has - the with statement this is the preferred way: - p.begin_group(1, '{') - ... - p.end_group(1, '}') - The python 2.5 expression would be this: + @contextmanager + def indent(self, indent): + """`with`-statement support for indenting/dedenting.""" + self.indentation += indent + try: + yield + finally: + self.indentation -= indent + + @contextmanager + def group(self, indent=0, open="", close=""): + """Context manager for an indented group. + with p.group(1, '{', '}'): - ... - The first parameter specifies the indentation for the next line ( - usually the width of the opening text), the second the opening text. - All parameters are optional. + + The first parameter specifies the indentation for the next line + (usually the width of the opening text), the second and third the + opening and closing delimiters. """ if open: self.text(open) @@ -239,6 +261,15 @@ self.group_stack.append(group) self.group_queue.enq(group) self.indentation += indent + try: + yield + finally: + self.indentation -= indent + group = self.group_stack.pop() + if not group.breakables: + self.group_queue.remove(group) + if close: + self.text(close) def _enumerate(self, seq): """Like enumerate, but with an upper limit on the number of items.""" @@ -250,19 +281,6 @@ return yield idx, x - def end_group(self, dedent=0, close=""): - """End a group. - - See `begin_group` for more details. - - """ - self.indentation -= dedent - group = self.group_stack.pop() - if not group.breakables: - self.group_queue.remove(group) - if close: - self.text(close) - def flush(self): """Flush data that is left in the buffer.""" if self.snans: @@ -276,121 +294,49 @@ self.buffer.clear() self.buffer_width = 0 + def getvalue(self): + assert isinstance(self.output, StringIO) + self.flush() + return self.output.getvalue() -def _get_mro(obj_class): - """Get a reasonable method resolution order of a class and its superclasses - for both old-style and new-style classes.""" - if not hasattr(obj_class, "__mro__"): # pragma: no cover - # Old-style class. Mix in object to make a fake new-style class. - try: - obj_class = type(obj_class.__name__, (obj_class, object), {}) - except TypeError: - # Old-style extension type that does not descend from object. - # FIXME: try to construct a more thorough MRO. - mro = [obj_class] - else: - mro = obj_class.__mro__[1:-1] - else: - mro = obj_class.__mro__ - return mro - - -class RepresentationPrinter(PrettyPrinter): - """Special pretty printer that has a `pretty` method that calls the pretty - printer for a python object. - - This class stores processing data on `self` so you must *never* use - this class in a threaded environment. Always lock it or - reinstanciate it. Instances also have a verbose flag callbacks can - access to control their output. For example the default instance - repr prints all attributes and methods that are not prefixed by an - underscore if the printer is in verbose mode. - - """ - - def __init__( - self, - output, - verbose=False, - max_width=79, - newline="\n", - singleton_pprinters=None, - type_pprinters=None, - deferred_pprinters=None, - max_seq_length=MAX_SEQ_LENGTH, - ): - - super().__init__(output, max_width, newline, max_seq_length=max_seq_length) - self.verbose = verbose - self.stack = [] - if singleton_pprinters is None: - singleton_pprinters = _singleton_pprinters.copy() - self.singleton_pprinters = singleton_pprinters - if type_pprinters is None: - type_pprinters = _type_pprinters.copy() - self.type_pprinters = type_pprinters - if deferred_pprinters is None: - deferred_pprinters = _deferred_type_pprinters.copy() - self.deferred_pprinters = deferred_pprinters - - def pretty(self, obj): - """Pretty print the given object.""" - obj_id = id(obj) - cycle = obj_id in self.stack - self.stack.append(obj_id) - self.begin_group() - try: - obj_class = _safe_getattr(obj, "__class__", None) or type(obj) - # First try to find registered singleton printers for the type. - try: - printer = self.singleton_pprinters[obj_id] - except (TypeError, KeyError): - pass - else: - return printer(obj, self, cycle) - # Next walk the mro and check for either: - # 1) a registered printer - # 2) a _repr_pretty_ method - for cls in _get_mro(obj_class): - if cls in self.type_pprinters: - # printer registered in self.type_pprinters - return self.type_pprinters[cls](obj, self, cycle) - else: - # deferred printer - printer = self._in_deferred_types(cls) - if printer is not None: - return printer(obj, self, cycle) - else: - # Finally look for special method names. - # Some objects automatically create any requested - # attribute. Try to ignore most of them by checking for - # callability. - if "_repr_pretty_" in cls.__dict__: - meth = cls._repr_pretty_ - if callable(meth): - return meth(obj, self, cycle) - return _default_pprint(obj, self, cycle) - finally: - self.end_group() - self.stack.pop() - - def _in_deferred_types(self, cls): - """Check if the given class is specified in the deferred type registry. - - Returns the printer from the registry if it exists, and None if - the class is not in the registry. Successful matches will be - moved to the regular type registry for future use. + def repr_call(self, func_name, args, kwargs, *, force_split=False): + """Helper function to represent a function call. + - func_name, args, and kwargs should all be pretty obvious. + - If split_lines, we'll force one-argument-per-line; otherwise we'll place + calls that fit on a single line (and split otherwise). """ - mod = _safe_getattr(cls, "__module__", None) - name = _safe_getattr(cls, "__name__", None) - key = (mod, name) - printer = None - if key in self.deferred_pprinters: - # Move the printer over to the regular registry. - printer = self.deferred_pprinters.pop(key) - self.type_pprinters[cls] = printer - return printer + assert isinstance(func_name, str) + if func_name.startswith(("lambda:", "lambda ")): + func_name = f"({func_name})" + self.text(func_name) + all_args = [(None, v) for v in args] + list(kwargs.items()) + if not force_split: + # We're OK with printing this call on a single line, but will it fit? + # If not, we'd rather fall back to one-argument-per-line instead. + p = RepresentationPrinter() + for k, v in all_args: + if k: + p.text(f"{k}=") + p.pretty(v) + p.text(", ") + force_split = self.max_width <= self.output_width + len(p.getvalue()) + + with self.group(indent=4, open="(", close=""): + all_args = [(None, v) for v in args] + list(kwargs.items()) + for i, (k, v) in enumerate(all_args): + if force_split: + self.break_() + elif i: + self.breakable() + if k: + self.text(f"{k}=") + self.pretty(v) + if force_split or i + 1 < len(all_args): + self.text(",") + if all_args and force_split: + self.break_() + self.text(")") # after dedent class Printable: @@ -425,8 +371,7 @@ def output(self, stream, output_width): self.group.breakables.popleft() if self.group.want_break: - stream.write(self.pretty.newline) - stream.write(" " * self.indentation) + stream.write("\n" + " " * self.indentation) return self.indentation if not self.group.breakables: self.pretty.group_queue.remove(self.group) @@ -471,46 +416,6 @@ pass -def _default_pprint(obj, p, cycle): - """The default print function. - - Used if an object does not provide one and it's none of the builtin - objects. - - """ - klass = _safe_getattr(obj, "__class__", None) or type(obj) - if _safe_getattr(klass, "__repr__", None) is not object.__repr__: - # A user-provided repr. Find newlines and replace them with p.break_() - _repr_pprint(obj, p, cycle) - return - p.begin_group(1, "<") - p.pretty(klass) - p.text(f" at 0x{id(obj):x}") - if cycle: - p.text(" ...") - elif p.verbose: - first = True - for key in dir(obj): - if not key.startswith("_"): - try: - value = getattr(obj, key) - except AttributeError: - continue - if isinstance(value, types.MethodType): - continue - if not first: - p.text(",") - p.breakable() - p.text(key) - p.text("=") - step = len(key) + 1 - p.indentation += step - p.pretty(value) - p.indentation -= step - first = False - p.end_group(1, ">") - - def _seq_pprinter_factory(start, end, basetype): """Factory that returns a pprint function useful for sequences. @@ -531,16 +436,15 @@ if cycle: return p.text(start + "..." + end) step = len(start) - p.begin_group(step, start) - for idx, x in p._enumerate(obj): - if idx: + with p.group(step, start, end): + for idx, x in p._enumerate(obj): + if idx: + p.text(",") + p.breakable() + p.pretty(x) + if len(obj) == 1 and type(obj) is tuple: + # Special case for 1-item tuples. p.text(",") - p.breakable() - p.pretty(x) - if len(obj) == 1 and type(obj) is tuple: - # Special case for 1-item tuples. - p.text(",") - p.end_group(step, end) return inner @@ -566,22 +470,20 @@ p.text(basetype.__name__ + "()") else: step = len(start) - p.begin_group(step, start) - # Like dictionary keys, we will try to sort the items if there - # aren't too many - items = obj - if not (p.max_seq_length and len(obj) >= p.max_seq_length): - try: - items = sorted(obj) - except Exception: - # Sometimes the items don't sort. - pass - for idx, x in p._enumerate(items): - if idx: - p.text(",") - p.breakable() - p.pretty(x) - p.end_group(step, end) + with p.group(step, start, end): + # Like dictionary keys, try to sort the items if there aren't too many + items = obj + if not (p.max_seq_length and len(obj) >= p.max_seq_length): + try: + items = sorted(obj) + except Exception: + # Sometimes the items don't sort. + pass + for idx, x in p._enumerate(items): + if idx: + p.text(",") + p.breakable() + p.pretty(x) return inner @@ -602,15 +504,14 @@ if cycle: return p.text("{...}") - p.begin_group(1, start) - for idx, key in p._enumerate(obj): - if idx: - p.text(",") - p.breakable() - p.pretty(key) - p.text(": ") - p.pretty(obj[key]) - p.end_group(1, end) + with p.group(1, start, end): + for idx, key in p._enumerate(obj): + if idx: + p.text(",") + p.breakable() + p.pretty(key) + p.text(": ") + p.pretty(obj[key]) inner.__name__ = f"_dict_pprinter_factory({start!r}, {end!r}, {basetype!r})" return inner @@ -618,21 +519,11 @@ def _super_pprint(obj, p, cycle): """The pprint for the super type.""" - try: - # This section works around various pypy versions that don't do - # have the same attributes on super objects - obj.__thisclass__ - obj.__self__ - except AttributeError: # pragma: no cover - assert PYPY - _repr_pprint(obj, p, cycle) - return - p.begin_group(8, "<super: ") - p.pretty(obj.__thisclass__) - p.text(",") - p.breakable() - p.pretty(obj.__self__) - p.end_group(8, ">") + with p.group(8, "<super: ", ">"): + p.pretty(obj.__thisclass__) + p.text(",") + p.breakable() + p.pretty(obj.__self__) def _re_pattern_pprint(obj, p, cycle): @@ -720,13 +611,12 @@ if obj.__class__.__module__ not in ("exceptions", "builtins"): name = f"{obj.__class__.__module__}.{name}" step = len(name) + 1 - p.begin_group(step, name + "(") - for idx, arg in enumerate(getattr(obj, "args", ())): - if idx: - p.text(",") - p.breakable() - p.pretty(arg) - p.end_group(step, ")") + with p.group(step, name + "(", ")"): + for idx, arg in enumerate(getattr(obj, "args", ())): + if idx: + p.text(",") + p.breakable() + p.pretty(arg) def _repr_float_counting_nans(obj, p, cycle): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/vendor/tlds-alpha-by-domain.txt new/hypothesis-python-6.61.2/src/hypothesis/vendor/tlds-alpha-by-domain.txt --- old/hypothesis-python-6.61.0/src/hypothesis/vendor/tlds-alpha-by-domain.txt 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/vendor/tlds-alpha-by-domain.txt 2023-01-07 11:48:18.000000000 +0100 @@ -1,4 +1,4 @@ -# Version 2022121000, Last Updated Sat Dec 10 07:07:02 2022 UTC +# Version 2022123100, Last Updated Sat Dec 31 07:07:01 2022 UTC AAA AARP ABARTH @@ -720,7 +720,6 @@ LOANS LOCKER LOCUS -LOFT LOL LONDON LOTTE @@ -1057,7 +1056,6 @@ SELECT SENER SERVICES -SES SEVEN SEW SEX diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/src/hypothesis/version.py new/hypothesis-python-6.61.2/src/hypothesis/version.py --- old/hypothesis-python-6.61.0/src/hypothesis/version.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/src/hypothesis/version.py 2023-01-07 11:48:18.000000000 +0100 @@ -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, 61, 0) +__version_info__ = (6, 61, 2) __version__ = ".".join(map(str, __version_info__)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tests/cover/test_falsifying_example_output.py new/hypothesis-python-6.61.2/tests/cover/test_falsifying_example_output.py --- old/hypothesis-python-6.61.0/tests/cover/test_falsifying_example_output.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tests/cover/test_falsifying_example_output.py 2023-01-07 11:48:18.000000000 +0100 @@ -12,12 +12,6 @@ from hypothesis import Phase, example, given, settings, strategies as st -OUTPUT_NO_BREAK = """ -Falsifying explicit example: test( - x={0!r}, y={0!r}, -) -""" - OUTPUT_WITH_BREAK = """ Falsifying explicit example: test( x={0!r}, @@ -26,9 +20,9 @@ """ -@pytest.mark.parametrize("line_break,input", [(False, "0" * 10), (True, "0" * 100)]) -def test_inserts_line_breaks_only_at_appropriate_lengths(line_break, input): - @example(input, input) +@pytest.mark.parametrize("n", [10, 100]) +def test_inserts_line_breaks_only_at_appropriate_lengths(n): + @example("0" * n, "0" * n) @given(st.text(), st.text()) def test(x, y): assert x < y @@ -36,8 +30,7 @@ with pytest.raises(AssertionError) as err: test() - expected = (OUTPUT_WITH_BREAK if line_break else OUTPUT_NO_BREAK).format(input) - assert expected.strip() == "\n".join(err.value.__notes__) + assert OUTPUT_WITH_BREAK.format("0" * n).strip() == "\n".join(err.value.__notes__) @given(kw=st.none()) @@ -61,4 +54,4 @@ with pytest.raises(AssertionError) as err: fn(1, 2, 3) - assert "1, 2, 3" in "\n".join(err.value.__notes__) + assert "1,\n 2,\n 3,\n" in "\n".join(err.value.__notes__) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tests/cover/test_pretty.py new/hypothesis-python-6.61.2/tests/cover/test_pretty.py --- old/hypothesis-python-6.61.0/tests/cover/test_pretty.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tests/cover/test_pretty.py 2023-01-07 11:48:18.000000000 +0100 @@ -49,7 +49,6 @@ import re from collections import Counter, OrderedDict, defaultdict, deque -from io import StringIO import pytest @@ -380,12 +379,10 @@ type_pprint_wrapper.called = False - stream = StringIO() - printer = pretty.RepresentationPrinter(stream) + printer = pretty.RepresentationPrinter() printer.type_pprinters[type] = type_pprint_wrapper printer.pretty(MyObj) - printer.flush() - output = stream.getvalue() + output = printer.getvalue() assert output == f"{__name__}.MyObj" assert type_pprint_wrapper.called @@ -576,26 +573,6 @@ assert r.pattern == r2.pattern and r.flags == r2.flags -class CustomStuff: - def __init__(self): - self.hi = 1 - self.bye = "fish" - self.spoon = self - - @property - def oops(self): - raise AttributeError("Nope") - - def squirrels(self): - pass - - -def test_custom(): - assert "bye" not in pretty.pretty(CustomStuff()) - assert "bye=" in pretty.pretty(CustomStuff(), verbose=True) - assert "squirrels" not in pretty.pretty(CustomStuff(), verbose=True) - - def test_print_builtin_function(): assert pretty.pretty(abs) == "abs" @@ -604,19 +581,8 @@ assert pretty.pretty(test_pretty_function) == "test_pretty_function" -def test_empty_printer(): - printer = pretty.RepresentationPrinter( - StringIO(), - singleton_pprinters={}, - type_pprinters={int: pretty._repr_pprint, list: pretty._repr_pprint}, - deferred_pprinters={}, - ) - printer.pretty([1, 2, 3]) - assert printer.output.getvalue() == "[1, 2, 3]" - - def test_breakable_at_group_boundary(): - assert "\n" in pretty.pretty([[], "000000"], max_width=5) + assert "\n" in pretty.pretty([[], "0" * 80]) @pytest.mark.parametrize( @@ -631,3 +597,19 @@ ) def test_nan_reprs(obj, rep): assert pretty.pretty(obj) == rep + + +def _repr_call(*args, **kwargs): + p = pretty.RepresentationPrinter() + p.repr_call(*args, **kwargs) + return p.getvalue() + + +@pytest.mark.parametrize("func_name", ["f", "lambda: ...", "lambda *args: ..."]) +def test_repr_call(func_name): + fn = f"({func_name})" if func_name.startswith(("lambda:", "lambda ")) else func_name + aas = "a" * 100 + assert _repr_call(func_name, (1, 2), {}) == f"{fn}(1, 2)" + assert _repr_call(func_name, (aas,), {}) == f"{fn}(\n {aas!r},\n)" + assert _repr_call(func_name, (), {"a": 1, "b": 2}) == f"{fn}(a=1, b=2)" + assert _repr_call(func_name, (), {"x": aas}) == f"{fn}(\n x={aas!r},\n)" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tests/cover/test_randoms.py new/hypothesis-python-6.61.2/tests/cover/test_randoms.py --- old/hypothesis-python-6.61.0/tests/cover/test_randoms.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tests/cover/test_randoms.py 2023-01-07 11:48:18.000000000 +0100 @@ -50,6 +50,7 @@ define_method_strategy("betavariate", alpha=beta_param, beta=beta_param) +define_method_strategy("binomialvariate", n=st.integers(min_value=1), p=st.floats(0, 1)) define_method_strategy("gammavariate", alpha=beta_param, beta=beta_param) define_method_strategy("weibullvariate", alpha=beta_param, beta=beta_param) define_method_strategy("choice", seq=seq_param) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tests/numpy/test_gen_data.py new/hypothesis-python-6.61.2/tests/numpy/test_gen_data.py --- old/hypothesis-python-6.61.0/tests/numpy/test_gen_data.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tests/numpy/test_gen_data.py 2023-01-07 11:48:18.000000000 +0100 @@ -340,8 +340,12 @@ pass +np_version = tuple(int(x) for x in np.__version__.split(".")[:2]) + + @pytest.mark.parametrize("fill", [False, True]) -@fails_with(InvalidArgument) +# Overflowing elements deprecated upstream in Numpy 1.24 :-) +@fails_with(InvalidArgument if np_version < (1, 24) else DeprecationWarning) @given(st.data()) def test_overflowing_integers_are_deprecated(fill, data): kw = {"elements": st.just(300)} @@ -372,7 +376,12 @@ kw = {"elements": st.nothing(), "fill": strat} else: kw = {"elements": strat} - arr = data.draw(nps.arrays(dtype=dtype, shape=(1,), **kw)) + try: + arr = data.draw(nps.arrays(dtype=dtype, shape=(1,), **kw)) + except RuntimeWarning: + assert np_version >= (1, 24), "New overflow-on-cast detection" + raise InvalidArgument("so the test passes") from None + try: # This is a float or complex number, and has overflowed to infinity, # triggering our deprecation for overflow. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tests/pytest/test_capture.py new/hypothesis-python-6.61.2/tests/pytest/test_capture.py --- old/hypothesis-python-6.61.0/tests/pytest/test_capture.py 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tests/pytest/test_capture.py 2023-01-07 11:48:18.000000000 +0100 @@ -12,7 +12,7 @@ import pytest -from hypothesis.internal.compat import PYPY, WINDOWS, escape_unicode_characters +from hypothesis.internal.compat import WINDOWS, escape_unicode_characters pytest_plugins = "pytester" @@ -102,8 +102,7 @@ timeout_token = ": FailedHealthCheck" def_line = get_line_num(def_token, result) timeout_line = get_line_num(timeout_token, result) - seven_min = (3, 9) if PYPY else (3, 8) - expected = 6 if sys.version_info[:2] < seven_min else 7 + expected = 6 if sys.version_info[:2] < (3, 8) else 7 assert timeout_line - def_line == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-python-6.61.0/tox.ini new/hypothesis-python-6.61.2/tox.ini --- old/hypothesis-python-6.61.0/tox.ini 2022-12-11 22:18:00.000000000 +0100 +++ new/hypothesis-python-6.61.2/tox.ini 2023-01-07 11:48:18.000000000 +0100 @@ -49,6 +49,7 @@ deps = -r../requirements/test.txt pandas~=1.0.5 + numpy~=1.23.5 commands = python -bb -X dev -m pytest tests/pandas -n auto