Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Registering a type inheriting from Sequence #2951

Closed
mristin opened this issue Apr 30, 2021 · 2 comments · Fixed by #2952
Closed

[Bug] Registering a type inheriting from Sequence #2951

mristin opened this issue Apr 30, 2021 · 2 comments · Fixed by #2952
Labels
bug something is clearly wrong here

Comments

@mristin
Copy link
Contributor

mristin commented Apr 30, 2021

Hi,
I observe a strange behavior when I create a class that inherits from Sequence[str] and registering it with Hypothesis. Namely, the generating strategy for that class is added to one of generating strategies for general Sequence's.

Perhaps it is related to #2940?

Please have a look:

from typing import Sequence, Union, overload

import hypothesis.strategies as st

class Lines(Sequence[str]):
    """Represent a sequence of text lines."""

    def __new__(cls, lines: Sequence[str]) -> "Lines":
        assert all('\n' not in line and '\r' not in line for line in lines)
        return cast(Lines, lines)

    def __add__(self, other: "Lines") -> "Lines":
        raise NotImplementedError("Only for type annotations")

    # pylint: disable=function-redefined

    @overload
    def __getitem__(self, index: int) -> str:
        pass

    @overload
    def __getitem__(self, index: slice) -> "Lines":
        pass

    def __getitem__(self, index: Union[int, slice]) -> Union[str, "Lines"]:
        raise NotImplementedError("Only for type annotations")

    def __len__(self) -> int:
        raise NotImplementedError("Only for type annotations")

st.register_type_strategy(
    Lines,
    st.fixed_dictionaries(
        {'lines': st.lists(st.text())
            .filter(
            lambda lines:
            all(
                '\n' not in line and '\r' not in line
                for line in lines))
        }
    ).map(lambda d: Lines(**d))
)

strategy = st.from_type(Lines)
assert (str(strategy) ==
        "fixed_dictionaries("
        "{'lines': lists(text())"
        ".filter(lambda lines: <unknown>)})"
        ".map(lambda d: <unknown>)")


# Now let's test that the strategy for ``Sequence[int]`` did not change just because
# we registered a strategy for ``Lines``.
strategy = st.from_type(Sequence[int])

# NOTE: something is strange here.
assert (str(strategy) ==
        "one_of("
        "binary(), "
        "lists(integers()), "
        "fixed_dictionaries("
        "{'lines': lists(text())"
        ".filter(lambda lines: <unknown>)})"
        ".map(lambda d: <unknown>))")
@mristin
Copy link
Contributor Author

mristin commented Apr 30, 2021

This line seems to be the culprit, but I am not sure:

if is_generic_type(k) and try_issubclass(k, thing)

Consider the following snippet (you can just append it to the above example):

import hypothesis.strategies._internal.types

is_subclass = hypothesis.strategies._internal.types.try_issubclass(Lines, Sequence[int])
is_generic_type = hypothesis.strategies._internal.types.is_generic_type(Lines)

assert is_subclass and is_generic_type

@mristin
Copy link
Contributor Author

mristin commented Apr 30, 2021

Perhaps the problem is in is_subclass since you don't check for __args__?

def try_issubclass(thing, superclass):
    thing = getattr(thing, "__origin__", None) or thing
    superclass = getattr(superclass, "__origin__", None) or superclass
    try:
        return issubclass(thing, superclass)
    except (AttributeError, TypeError):
        # Some types can't be the subject or object of an instance or subclass check
        return False

mristin added a commit to mristin/python-by-contract-corpus that referenced this issue Apr 30, 2021
Registering types with Hypothesis which inherit from `typing` generic
types causes unexpected Hypothesis strategies, see [1]. Hence this patch
removes the inheritance and implements the remainder of the methods so
that duck typing works with mypy.

[1]: HypothesisWorks/hypothesis#2951
mristin added a commit to mristin/python-by-contract-corpus that referenced this issue Apr 30, 2021
Registering types with Hypothesis which inherit from `typing` generic
types causes unexpected Hypothesis strategies, see [1]. Hence this patch
removes the inheritance and implements the remainder of the methods so
that duck typing works with mypy.

[1]: HypothesisWorks/hypothesis#2951
@Zac-HD Zac-HD added the bug something is clearly wrong here label May 1, 2021
@mristin mristin changed the title [Bug?] Registering a type inheriting from Sequence [Bug] Registering a type inheriting from Sequence Aug 16, 2021
halstead pushed a commit to openembedded/openembedded-core that referenced this issue Aug 19, 2021
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
stefan-hartmann-lgs pushed a commit to hexagon-geo-surv/poky that referenced this issue Aug 20, 2021
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

(From OE-Core rev: 9da4590754a2d3421ea621c28ec4e6efe058b7b4)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
halstead pushed a commit to openembedded/openembedded-core that referenced this issue Aug 20, 2021
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
seambot pushed a commit to seamapi/poky that referenced this issue Aug 20, 2021
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

(From OE-Core rev: 1f2276c6d0312854caacebe1c83dee57474f1bb2)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
daregit pushed a commit to daregit/yocto-combined that referenced this issue May 22, 2024
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

(From OE-Core rev: 1f2276c6d0312854caacebe1c83dee57474f1bb2)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
daregit pushed a commit to daregit/yocto-combined that referenced this issue May 22, 2024
6.14.8 - 2021-08-16
This patch ensures that registering a strategy for a subclass of a
parametrised generic type such as class Lines(Sequence[str]): will not
“leak” into unrelated strategies such as st.from_type(Sequence[int])
(issue #2951). Unfortunately this fix requires PEP 560, meaning Python
3.7 or later.

6.14.7 - 2021-08-14
This patch fixes issue #3050, where attrs classes could cause an internal
error in the ghostwriter.

6.14.6 - 2021-08-07
This patch improves the error message for issue #3016, where PEP 585 builtin
generics with self-referential forward-reference strings cannot be resolved
to a strategy by from_type().

References:
HypothesisWorks/hypothesis#2951
https://www.python.org/dev/peps/pep-0560
HypothesisWorks/hypothesis#3050
https://www.python.org/dev/peps/pep-0585

(From OE-Core rev: 1f2276c6d0312854caacebe1c83dee57474f1bb2)

Signed-off-by: Tim Orling <timothy.t.orling@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something is clearly wrong here
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants