[issue47074] Convenient `simplefilter()` in `warnings.catch_warnings()`

2022-03-20 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

Many pytest users would like a concise way to either suppress warnings, or 
convert them to errors [1].  The current best approach is:

with warnings.catch_warnings():
warnings.simplefilter("ignore")  # or "error"

but even this becomes tediously verbose when repeated in hundreds of tests 
(which I suspect is responsible for many misuses of `pytest.raises()`).  Since 
these two functions take disjoint arguments [2], I propose allowing 
catch_warnings() to accept arguments for simplefilter() and forward them on:

with warnings.catch_warnings("ignore"):  # or "error"

I have a quick implementation at [3] which I can finish if the idea is 
acceptable.  Although I don't have a concrete use-case for more than the 
'action' and 'category' arguments, forwarding all rather than some makes the 
semantics very simple.

I'd emphasize again that this is very much a convenience-focussed change: I 
estimate that 95% of all uses will pass only `action="error"` or 
`action="ignore"`.  Supporting a concise and simple interface for this seems 
worth the small complication to the design of the warnings module.


[1] see e.g. https://github.com/pytest-dev/pytest/issues/9404 for a long thread
[2] unlike `filterwarnings()`, which has a `module=` argument which would 
collide with `catch_warnings()`
[3] 
https://github.com/python/cpython/compare/main...Zac-HD:zac-hd/one-line-catch-warnings

------
components: Library (Lib)
messages: 415647
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: Convenient `simplefilter()` in `warnings.catch_warnings()`
type: enhancement
versions: Python 3.11

___
Python tracker 
<https://bugs.python.org/issue47074>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46026] importlib.resources.read_text() raises FileNotFound

2021-12-09 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

This may have appeared in the wild, via the backport, in

https://github.com/Nuitka/Nuitka/issues/1274 and
https://github.com/Nuitka/Nuitka/commit/ffe861cfe972c6bf19f9eea1ff95e35d0e4240b4

--

___
Python tracker 
<https://bugs.python.org/issue46026>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46026] importlib.resources.read_text() raises FileNotFound

2021-12-09 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
nosy: +brett.cannon, jaraco

___
Python tracker 
<https://bugs.python.org/issue46026>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46026] importlib.resources.read_text() raises FileNotFound

2021-12-09 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

Testing Hypothesis with Python 3.11.0a3, I've triggered a frustrating 
regression in importlib.resources:


# Both work in Python 3.9 and 3.10, but both fail in 3.11.0a3
from importlib.resources import files, read_text
read_text("hypothesis.vendor", "tlds-alpha-by-domain.txt")
files("hypothesis.vendor").joinpath("tlds-alpha-by-domain.txt").read_text()


Traceback (most recent call last):
  ...
  File "example.py", line 4, in 
read_text("hypothesis.vendor", "tlds-alpha-by-domain.txt")
^^
  File "python3.11/importlib/_legacy.py", line 25, in wrapper
return func(*args, **kwargs)
   ^
  File "python3.11/importlib/_legacy.py", line 67, in read_text
with open_text(package, resource, encoding, errors) as fp:
 ^^
  File "python3.11/importlib/_legacy.py", line 25, in wrapper
return func(*args, **kwargs)
   ^
  File "python3.11/importlib/_legacy.py", line 50, in open_text
return (_common.files(package) / _common.normalize_path(resource)).open(
   ^
  File "python3.11/importlib/_adapters.py", line 141, in open
raise FileNotFoundError("Can't open orphan path")
^
FileNotFoundError: Can't open orphan path


At first I thought this was just a problem with the _legacy shims, but since it 
also affects the new files() API it might be more serious.

--
components: Library (Lib)
messages: 408107
nosy: Zac Hatfield-Dodds, barry
priority: normal
severity: normal
status: open
title: importlib.resources.read_text() raises FileNotFound
type: behavior
versions: Python 3.11

___
Python tracker 
<https://bugs.python.org/issue46026>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42109] Use hypothesis for testing the standard library, falling back to stubs

2021-11-11 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

I've recently had [1] reported, which makes https://bugs.python.org/issue45738 
the *third* parser bug [2] that Hypothesmith caught after release, and the 
second in a stable version - so I'll be maintaining a workaround for some time.

I remain happy to help run these tests upstream where they would impact fewer 
people.


[1] https://github.com/Zac-HD/hypothesmith/issues/16 and 
https://github.com/psf/black/pull/2592#issuecomment-966745240
[2] following https://bugs.python.org/issue42218 and 
https://bugs.python.org/issue40661

--

___
Python tracker 
<https://bugs.python.org/issue42109>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45738] 3.11 exec raises SystemError instead of SyntaxError on char after line continuation

2021-11-11 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

It looks like this also affects Python 3.9.8, which makes me very suspicious of 
https://bugs.python.org/issue45494 as the probable cause.

See https://github.com/Zac-HD/hypothesmith/issues/16 and 
https://github.com/psf/black/pull/2592#issuecomment-966745240 for reports.

--
nosy: +Zac Hatfield-Dodds
versions: +Python 3.9

___
Python tracker 
<https://bugs.python.org/issue45738>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45607] Make it possible to enrich an exception's error message

2021-10-25 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

This code shows my current best workaround based on a wrapper exception, with 
the traceback below annotating the additional details that I'd prefer to omit 
for clarity:


$ python example.py
Traceback (most recent call last):
  File "example.py", line 8, in 
raise AssertionError(why)
AssertionError: Failed!
# These 
lines are
The above exception was the direct cause of the following exception:# 
confusing for new 
# 
users, and they
Traceback (most recent call last):  # only 
exist due 
  File "example.py", line 10, in# to 
implementation
raise Explanation(msg) from e   # via 
the Explanation
Explanation:# 
wrapper type :-(
You can reproduce this error by ...
...


The motivation for this is that we'd like to use ExceptionGroup to indicate 
that `MultipleFailures` is a group of exceptions, and replace our current 
print()-based method of reporting the details of the inner exceptions.

--

___
Python tracker 
<https://bugs.python.org/issue45607>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44246] 3.10 beta 1: breaking change in importlib.metadata entry points

2021-05-29 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

Just chiming in with a plea to slow down the rate of changes to 
importlib.metadata - I understand that you want to tidy up the API, but even 
deprecations cause substantial work downstream.  Would it really be so bad to 
support the older APIs until they go end-of-life in CPython?

For example, in Hypothesis we care a great deal about compatibility with all 
supported Python versions (including treating warnings as errors) and try to 
minimize the hard dependencies.  As a result, our entry-points handling looks 
like this:
https://github.com/HypothesisWorks/hypothesis/blob/0a90ed6edf56319149956c7321d4110078a5c228/hypothesis-python/src/hypothesis/entry_points.py

Change can be worth the cost, but there *is* a cost and the packaging ecosystem 
is already painfully complex and fragmented.  Compatibility should be a 
foundational principle, not an optional extra _if someone presents a compelling 
use case!_

I'm also seriously concerned that you take GitHub links as an indication of who 
is affected.  Python is very very widely used, including in environments that 
don't feed much back into the GitHub-open-source space, and I think it's 
important to avoid breaking things for low-visibility users too.

--
nosy: +Zac Hatfield-Dodds

___
Python tracker 
<https://bugs.python.org/issue44246>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42109] Use hypothesis for testing the standard library, falling back to stubs

2021-05-19 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

> Okay, well, I'm trying to understand minithesis.py, but I am despairing. The 
> shrinking code (really everything in class TestingState) is too much to grok. 
> ... I suppose I have to read the paper at 
> https://drmaciver.github.io/papers/reduction-via-generation-preview.pdf ... I 
> am still unclear on some basics too, but presumably it's all related.

Shrinking is probably not important to understand, since it's *not* 
particularly related to anything but implementation details.  The abstract of 
that paper explains why the design is important - integrated shrinking means we 
can report minimal (easier-to-understand) failing examples with zero user 
effort, and guarantee that all shrunk examples could have been generated.

TestingState is, roughly, the `@given()` decorator internals: responsible for 
deciding how many times to run the wrapped test function, and how.  Note the 
three phases (generate, target, shrink) - the distribution of examples can 
depend on the behaviour of the test function on earlier inputs.  This is _more_ 
complex in Hypothesis and thus challenging to document.

The important concept is that input examples are generated by a Possibility (ie 
Strategy), which internally makes a sequence of choices; and that sequence is 
sourced from a maybe-empty known prefix (e.g. replaying failures, mutating 
previous inputs) with the suffix determined by a PRNG.


I feel like I'm explaining this badly, but there isn't a simple underlying 
thing to explain - Hypothesis works well because the user API is relatively 
simple, and then under the hood we have this many-layered stack of 
implementation details.  The synergies and coverage of otherwise-pathological 
cases this delivers is excellent, but "multiple years and PhDs worth of 
detailed synergistic work" is just intrinsically complicated.


> PS. What does "shortlex" mean?

Sort by length, and among equal-length strings sort in the normal 
(alphabetical) order.  For example: A < XY < ABC, etc.

--

___
Python tracker 
<https://bugs.python.org/issue42109>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42109] Use hypothesis for testing the standard library, falling back to stubs

2021-05-13 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

(I think structuring this as a high-level explanation is clearer than 
point-by-point replies - it covers most of them, but the logic is hopefully 
easier to follow)


The core idea of Hypothesis is that making random choices is equivalent to 
parsing a random bitstring:
- wrap your test function in a decorator which calls it many times with 
random inputs
- describe those inputs with strategies, (which are parser combinators)
- the bytes parsed by strategies can be provided by a Random() instance, 
saved to and loaded from a database, edited and (maybe) re-parsed into related 
or simpler inputs, etc.
Minithesis [1] is a complete implementation of this core, including strategies, 
shrinking, and the database, in a few hundred lines of Python.  I think reading 
this will answer most of your implementation questions.

Hypothesis is not the *only* property-based testing library for Python (there's 
pytest-quickcheck), but in the same sense that `six` is not the only py2/py3 
compatibility layer.  I attribute this to a combination of a better underlying 
model [2], and brute implementation effort to provide great error messages, 
integration with popular libraries, lots of strategies, related tooling, and so 
on.

[1] https://github.com/DRMacIver/minithesis
See also https://hypothesis.works/articles/how-hypothesis-works/ for an 
older writeup; the implementation details are a little outdated but it explains 
the motivations better.
[2] https://hypothesis.works/articles/types-and-properties/



So a "strategy" is an object (implementation detail: a parser combinator, 
instance of SearchStrategy), which tells Hypothesis how to convert a random 
bytestring into whatever object you've asked for.  This is a little unusual, 
but I haven't found a better way which still makes it easy to mix the strategy 
primitives with arbitrary user code such as "pick a username, ensure it's in 
the database, and then pass it to my test method".

I share your distaste for "Haskell in Python"; I don't think Hypothesis 
introduces more of that flavor than Numpy would introduce Fortran idioms - 
there's occasionally a resemblance, but they're both Python-first libraries and 
I'd attribute it mostly to the problem being solved.  FWIW Hypothesis 
deliberately rejected most of the design choices of QuickCheck, and 
implementation-wise has more in common with unixy fuzzing tools like AFL.

The strategies in our API can generally be divided into useful primitives (e.g. 
integers, floats, lists, tuples, sampled_from, one_of) and pre-composed 
strategies (booleans = sampled_from, dictionaries = map+lists-of-kv-tuples, 
builds = tuples+fixed_dictionaries+map).
Very specific strategies like emails() are included because they're a common 
need, and a naive implementation usually omits exactly the weirder and 
error-prone features that might reveal bugs.

We _are_ deliberately vague about the order in which we generate test data, 
because the distribution is full of heuristics and adapts itself to the 
behaviour of the test - including over multiple runs, thanks to the database.  
The exact details are also considered an implementation detail, and subject to 
change as we discover heuristics and sampling techniques which find bugs faster.

The upside here is writing effective strategies is straightforward:
- expressing more possible (valid) inputs is good, because e.g. if the bug 
triggers on NaN we'd have to generate some NaNs to detect it; and
- limiting use of rejection sampling (hypothesis.assume(), the .filter() 
method) is an obvious performance improvement - if only 20% of inputs we try to 
generate are valid, the test will take five times longer.
following which Hypothesis' backend (the "conjecture" engine) uses a large 
helping of heuristics and fancy code to ensure that we get a nice diverse 
sample from the inputs space.  Unfortunately there's a direct tension between 
high performance and explainable behaviour; Minithesis is readable mostly by 
virtue of not handling the hard edge cases.



I'll take my Hypothesmith [3] project for random Python programs as an example 
of a complex strategy.  It was inspired by CSmith [4] - but is considerably 
less sophisticated.  CSmith constructs semantically valid C programs; 
Hypothesmith (for now!) constructs a subset of syntatically-valid Python.  The 
basic idea is to "invert" the grammar: start with the root node, recursively 
construct a valid parse tree, and then serialise it out to a parsable input 
string.  Doing a better job would require more time than I had for a 
proof-of-concept, but no new insights; and the same applies to defining a 
strategy for semantically-valid code.  Being based on the grammar I'd guess 
it's unlikely to find corner cases in the grammar, but it might do so in the 
parser, or via e.g. `(tree := ast.parse(code)) == ast.parse(ast.unparse(tree))`

[issue43006] Changed behaviour of inspect.signature() in Python 3.10

2021-05-03 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

I think that with PEP-563 reverted, this issue has been fixed.

If we have a similar problem from e.g. PEP-649, I'll open another ticket then!

--
resolution:  -> fixed
stage:  -> resolved
status: open -> closed

___
Python tracker 
<https://bugs.python.org/issue43006>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43006] Changed behaviour of inspect.signature() in Python 3.10

2021-01-23 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

And I promise this is the last one:


import inspect
import typing

def f():
A = typing.TypeVar("A")

def same_type_args(a: A, b: A):
assert type(a) == type(b)

print(inspect.signature(same_type_args))
print(typing.get_type_hints(same_type_args))

f()


$ python3 t.py 
(a: ~A, b: ~A)
{'a': ~A, 'b': ~A}

$ python3.10 t.py 
(a: 'A', b: 'A')
Traceback (most recent call last):
  ...
NameError: name 'A' is not defined


My apologies to everyone involved here; I'm looking forward to postponed 
annotation evaluation, appreciate all your work on this, and regret that I have 
such bizzare bugs to report <3

--

___
Python tracker 
<https://bugs.python.org/issue43006>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43006] Changed behaviour of inspect.signature() in Python 3.10

2021-01-23 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

Aaaand it looks like another problem I'm having is also related:


import inspect

class T(typing.TypedDict):
a: int

print(inspect.signature(T))

was `(*args, **kwargs)` and now raises `ValueError: no signature found for 
builtin type `

--

___
Python tracker 
<https://bugs.python.org/issue43006>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43006] Changed behaviour of inspect.signature() in Python 3.10

2021-01-23 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

A closely related problem, also via 
https://github.com/HypothesisWorks/hypothesis/issues/2767


import inspect

def f(x) -> None:
pass

annotations = inspect.getfullargspec(f).annotations
assert annotations == {"return": None}, annotations


Under Python 3.10, annotations is now {"return": }

--

___
Python tracker 
<https://bugs.python.org/issue43006>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43006] Changed behaviour of inspect.signature() in Python 3.10

2021-01-22 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

Consider the following snippet, which passes on Python 3.9 and earlier:


import inspect

def f(x: int = None):
pass

print(inspect.signature(constructor))
assert inspect.signature(constructor).parameters["a"].annotation == int


But under Python 3.10 (alpha 4), the annotation is instead read as 
Optional[int].  This is correct for typing.get_type_hints(), but *not* for 
inspect.signature().

I therefore suspect that this is an accidental side-effect from support for 
PEP-563 deferred evaluation of annotations.

--
components: Library (Lib)
messages: 385524
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: Changed behaviour of inspect.signature() in Python 3.10
versions: Python 3.10

___
Python tracker 
<https://bugs.python.org/issue43006>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42195] Inconsistent __args__ between typing.Callable and collections.abc.Callable

2020-11-15 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

> @Hatfield-Dodds, if we changed typing.Callable to return ((int, int), str) 
> but collections.abc.Callable continued to return ([int, int], str), would 
> that suffice for your purposes?

For performance reasons I'd prefer that the return value be hashable for both, 
but we've already shipped the workarounds [0,1,2] for 3.9.0 and will maintain 
that until 3.9 reaches EOL in any case.

Whether we return (int, int, str) or ((int, int), str) doesn't make much 
difference to me, the latter will require a trivial patch to [2] so please do 
whatever makes most sense upstream.


> Also, maybe we should make builtins.callable generic as well?

I like this idea :-)


[0] https://hypothesis.readthedocs.io/en/latest/changes.html#v5-39-0
[1] 
https://github.com/HypothesisWorks/hypothesis/pull/2653/files#diff-c56f048e926cce76dc6cd811924136f5c97e0f68f59625869b4ab01f1dbe10e0L1473-R1480
[2] 
https://github.com/HypothesisWorks/hypothesis/pull/2653/files#diff-f6a209c019f3f6af11a027a0035e3fc736935d9920fd85da726f9abf4c325d6bR562-R567

--

___
Python tracker 
<https://bugs.python.org/issue42195>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42218] SystemError in compile builtin function

2020-10-31 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

Wow!  Thanks and congrats on the super-fast fix :-)


FYI Paul Ganssle has recently [1] started to work on adding property-based 
tests to CPython CI [2].  Once Paul gets the stubs and first set of tests 
working, I'll start moving the others over from my demo repo [3] to CPython 
master so we catch this kind of bug earlier in future.

[1] https://bugs.python.org/issue42109; see also 
https://bugs.python.org/issue38953
[2] https://pyfound.blogspot.com/2020/05/property-based-testing-for-python.html
[3] https://github.com/Zac-HD/stdlib-property-tests

--

___
Python tracker 
<https://bugs.python.org/issue42218>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42218] SystemError in compile builtin function

2020-10-31 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

In Python 3.9.0, running

compile('A.\u018a\\ ', '', 'single')

raises

SystemError:  returned a result with an error 
set

This is obviously invalid syntax, but it would still be nice to raise 
SyntaxError for that and the SystemError may be symptomatic of a bug.  
Unfortunately I have no insight to offer beyond this hand-minimised reproducer 
:-/

--
components: Interpreter Core
messages: 380053
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: SystemError in compile builtin function
versions: Python 3.9

___
Python tracker 
<https://bugs.python.org/issue42218>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42195] Inconsistent __args__ between typing.Callable and collections.abc.Callable

2020-10-29 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

Unfortunately I'm overcommitted for the next few weeks-months :-/

--

___
Python tracker 
<https://bugs.python.org/issue42195>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42195] Inconsistent __args__ between typing.Callable and collections.abc.Callable

2020-10-29 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

The two ways of getting a parametrised Callable have inconsistent __args__:

>>> import collections.abc, typing
>>> typing.Callable[[int, int], int].__args__
(int, int, int)
>>> collections.abc.Callable[[int, int], int].__args__
([int, int], int)

I discovered this while working on PEP 585 support in Hypothesis [1], where it 
is easy enough to work around but carries a potentially serious performance 
cost - the list means we cannot use the type as a cache key for non-`...` 
argument types.  

https://bugs.python.org/issue40494 and https://bugs.python.org/issue40398 may 
be related.

[1] https://github.com/HypothesisWorks/hypothesis/pull/2653

--
components: Library (Lib)
messages: 379869
nosy: Zac Hatfield-Dodds, gvanrossum, levkivskyi, serhiy.storchaka
priority: normal
severity: normal
status: open
title: Inconsistent __args__ between typing.Callable and 
collections.abc.Callable
type: behavior
versions: Python 3.10, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue42195>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38953] Untokenize and retokenize does not round-trip

2020-10-23 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

Thanks for your comments Terry - I'm delighted that it's useful.  It's been a 
while since I wrote that, and entirely possible that it's just a typo.

Hypothesis does indeed support unittest, including for multiple-failure 
reporting and so on. 
 You can see my unittest implementation of the tokenise tests at 
https://github.com/Zac-HD/stdlib-property-tests/blob/b5ef97f9e7fd1b0e7a028823e436f78f374cf0dc/tests/test_source_code.py#L87-L133

Subtests are a little tricky, because the default interaction is to store the 
subtests for *all* test cases generated by Hypothesis.  We therefore 
monkeypatch it to a no-op, but more sophisticated handling is almost certainly 
possible.  More generally, when using Hypothesis I would usually ask @given for 
single inputs and call the test method; which replaces the usual loop over a 
list of inputs with subTest.

An iterator interface is not available because in general (see e.g. 
`hypothesis.strategies.data()` or stateful testing) it is not possible to 
separate data generation from test execution, and also because Hypothesis uses 
feedback from previous inputs in deciding what to generate.  Instead of "for 
testcase in testcases: with subTest: ...", I'd write "@given(testcase=...) def 
test_foo(self, testcase): ...".


I've sent you an email for the other conversation.  (anyone else interested is 
invited to get in touch via zhd.dev :-))

--

___
Python tracker 
<https://bugs.python.org/issue38953>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39046] collections.abc.Reversible should not be a subclass of Hashable

2020-10-22 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

I'm closing this as not-a-bug.

The way protocols just check methods does make sense (thanks for your comment 
Guido!), and a later refactoring of the code that prompted this issue (to deal 
only in concrete classes) dissolved the problem.

--
resolution:  -> not a bug
stage:  -> resolved
status: open -> closed

___
Python tracker 
<https://bugs.python.org/issue39046>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue40668] Catastrophic loss of precision in colorsys module

2020-05-18 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

As part of the Mentored Sprints at PyCon US, Marielle wrote some property-based 
tests [1] for the colorsys module [2], which found two bugs.


Taking a YIQ color, converting to RGB, and back to YIQ can result in the Y 
coordinate varying by more 0.1 (where [0, 1] is the range of possible values).
For example: (0.0 1.0 2.2204460492503136e-16) -> RGB -> (0.0 
1.1102230246251568e-16 1.0)

Taking an RGB color and converting though HSV-RBG-HSV can result in very 
different saturation values - up to having S1==0 and S2==1.
For example: (0.0 1.0 2.2204460492503136e-16) -> RGB -> (0.0 
1.1102230246251568e-16 1.0)


You can reproduce additional examples and get error bounds from [3].


[1] https://pyfound.blogspot.com/2020/05/property-based-testing-for-python.html
[2] https://docs.python.org/3/library/colorsys.html
[3] https://github.com/Zac-HD/stdlib-property-tests/pull/13

--
components: Library (Lib)
messages: 369197
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: Catastrophic loss of precision in colorsys module
type: behavior
versions: Python 3.5, Python 3.6, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue40668>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue40661] The new parser segfaults when parsing invalid input

2020-05-18 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

I know what else it might find either, but I still think it's worth running 
property-based tests in CI to find out!  The demo I wrote for my language 
summit talk doesn't have any parser tests, but still would have caught this bug 
in the pull request that introduced it.


The specific reproducer here is odd, because it's reported as an internal error 
in Hypothesmith - I use the `compile()` builtin to check that strings valid 
against an approximate grammar are actually valid.

It's structurally less complex than typical outputs because it's only a 
fragment of the tree being generated, but because shrinking doesn't run for 
generation-time errors it's also much harder to interpret than usual.

--

___
Python tracker 
<https://bugs.python.org/issue40661>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue40661] The new parser segfaults when parsing invalid input

2020-05-17 Thread Zac Hatfield-Dodds


Zac Hatfield-Dodds  added the comment:

I understand from Paul Ganssle that this bug was found using Hypothesmith in my 
stdlib property tests (reported at 
https://github.com/Zac-HD/stdlib-property-tests/issues/14).

As discussed in https://github.com/we-like-parsers/cpython/issues/91 and 
https://pyfound.blogspot.com/2020/05/property-based-testing-for-python.html I'm 
keen to help out how I can, so if there's anything more specific than "write 
tools, write test, and wait" please let me know!

Best,
Zac

--
nosy: +Zac Hatfield-Dodds

___
Python tracker 
<https://bugs.python.org/issue40661>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue21444] __len__ can't return big numbers

2020-01-10 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
pull_requests: +17341
pull_request: https://github.com/python/cpython/pull/17934

___
Python tracker 
<https://bugs.python.org/issue21444>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue12159] Integer Overflow in __len__

2020-01-10 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
pull_requests: +17339
pull_request: https://github.com/python/cpython/pull/17934

___
Python tracker 
<https://bugs.python.org/issue12159>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue15718] Possible OverflowError in __len__ method undocumented (when called via len() function)

2020-01-10 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
pull_requests: +17340
pull_request: https://github.com/python/cpython/pull/17934

___
Python tracker 
<https://bugs.python.org/issue15718>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39227] OverflowError in len(range(2**63))

2020-01-05 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

The value for `len` internally passes through an `ssize_t`, which means that it 
raises OverflowError for (very) large collections.

This is admittedly only possible with collections such as `range` that do not 
store all their elements in memory, but it would still be nice to have 
`len(range(n)) == n` without caveats.

This was found via a teaching example and is now tracked in my repo of 
property-based tests for CPython:
https://github.com/rsokl/Learning_Python/pull/125
https://github.com/Zac-HD/stdlib-property-tests/blob/bb46996ca4500381ba09a8cd430caaddd71910bc/tests.py#L28-L34

Related to https://bugs.python.org/issue26423, but it's still present in the 
development branches for 3.7, 3.8, and 3.9; and instead of a wrong result it's 
an error (which is better!).

--
components: Interpreter Core
messages: 359394
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: OverflowError in len(range(2**63))
type: behavior
versions: Python 3.6, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue39227>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39046] collections.abc.Reversible should not be a subclass of Hashable

2019-12-14 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

>>> from collections.abc import Hashable, Reversible
>>> assert issubclass(Reversible, Hashable)

However, this is trivially wrong - lists are Reversible but not Hashable, and 
there is no reason to thing that reversible objects should all be hashable.

The versions of these classes in the typing module have the same problem.

--
components: Library (Lib)
messages: 358386
nosy: Zac Hatfield-Dodds
priority: normal
severity: normal
status: open
title: collections.abc.Reversible should not be a subclass of Hashable
type: behavior
versions: Python 3.6, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue39046>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38953] Untokenize and retokenize does not round-trip

2019-12-02 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

I've been working on a tool called Hypothesmith - 
https://github.com/Zac-HD/hypothesmith - to generate arbitrary Python source 
code, inspired by CSmith's success in finding C compiler bugs.  It's based on 
the grammar but ultimately only generates strings which `compile` accepts; this 
is the only way I know to answer the question "is the string valid Python"!

I should be clear that I don't think the minimal examples are representative of 
real problems that users may encounter!  However, fuzzing is very effective at 
finding important bugs if we can get these apparently-trivial ones out of the 
way by changing either the code or the test :-)

```python
@example("#")
@example("\n\\\n")
@example("#\n\x0cpass#\n")
@given(source_code=hypothesmith.from_grammar().map(fixup).filter(str.strip))
def test_tokenize_round_trip_string(source_code):
tokens = list(tokenize.generate_tokens(io.StringIO(source_code).readline))
outstring = tokenize.untokenize(tokens)  # may have changed whitespace from 
source
output = tokenize.generate_tokens(io.StringIO(outstring).readline)
assert [(t.type, t.string) for t in tokens] == [(t.type, t.string) for t in 
output]
```

Each of the `@example` cases are accepted by `compile` but fail the test; the 
`@given` case describes how to generate more such strings.  You can read more 
details in the Hypothesmith repo if interested.

I think these are real and probably unimportant bugs, but I'd love to start a 
conversation about what properties should *always* hold for functions dealing 
with Python source code - and how best to report research results if I can 
demonstrate that they don't!

(for example, lib2to3 has many similar failures but I don't want to open a long 
list of low-value issues)

--
components: Library (Lib)
messages: 357704
nosy: Zac Hatfield-Dodds, meador.inge
priority: normal
severity: normal
status: open
title: Untokenize and retokenize does not round-trip
type: behavior
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue38953>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38834] TypedDict: no way to tell which (if any) keys are optional at runtime

2019-11-17 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
keywords: +patch
pull_requests: +16717
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/17214

___
Python tracker 
<https://bugs.python.org/issue38834>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38834] TypedDict: no way to tell which (if any) keys are optional at runtime

2019-11-17 Thread Zac Hatfield-Dodds


New submission from Zac Hatfield-Dodds :

Consider the following cases:

```python
class A(typing.TypedDict):
a: int  # a is required

class B(A, total=False):
b: bool  # a is required, b is optional

class C(B):
c: str  # a is required, b is optional, c is required again
```

PEP-589 is clear about the semantics, and this is obvious enough when reading 
the code.  At runtime the __annotations__ attribute of each class gives us the 
set of allowed keys and the type of each corresponding value, but we have a 
problem:

- C has __total__==True, but b is not actually required.
- B has __total__==False, but a *is* required.
- I can't see any way to get the parent classes of a TypedDict class!

The _TypedDictMeta metaclass updates the attributes, but leaves no record of 
the parent type - at runtime A, B, and C all appear to inherit directly from 
dict.

After discussion on the typing-sig mailing list, I propose to add 
__required_keys__ and __optional_keys__ attributes to TypedDict subclasses, as 
frozensets of strings.

This will be very useful for Hypothesis' `from_type()` strategy, as well as for 
type-based validation frameworks like pydantic or typeguard.

--
components: Library (Lib)
messages: 356836
nosy: Zac Hatfield-Dodds, levkivskyi
priority: normal
severity: normal
status: open
title: TypedDict: no way to tell which (if any) keys are optional at runtime
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue38834>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue26967] argparse: allow_abbrev=False stops -vv from working

2019-06-22 Thread Zac Hatfield-Dodds


Change by Zac Hatfield-Dodds :


--
keywords: +patch
pull_requests: +14140
stage: needs patch -> patch review
pull_request: https://github.com/python/cpython/pull/14316

___
Python tracker 
<https://bugs.python.org/issue26967>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com