Skip to content

Incompatible Sequence types generated after register_type_strategy() #3767

@h4l

Description

@h4l

A from_type(Sequence[XXX]) strategy is able to generate instances of classes unrelated to XXX that are Sequence subtypes registered with register_type_strategy().

Probably best explained with an example. Both of these tests fail:

from collections import namedtuple
from collections.abc import Sequence

from hypothesis import given
from hypothesis import strategies as st


class Thing(namedtuple("Thing", [])):
    pass


class CustomSequence(Sequence):
    def __getitem__(self, i) -> Never:
        raise IndexError()

    def __len__(self) -> int:
        return 0


class Other:
    pass


st.register_type_strategy(Thing, st.builds(Thing))
st.register_type_strategy(CustomSequence, st.builds(CustomSequence))


@given(st.from_type(Sequence[Other]))
def test_thing_is_not_seq_of_other(others: Sequence[Other]) -> None:
    assert not isinstance(others, Thing)


@given(st.from_type(Sequence[Other]))
def test_customseq_is_not_seq_of_other(others: Sequence[Other]) -> None:
    assert not isinstance(others, CustomSequence)

I ran into this after upgrading from hypothesis 6.68.2 to 6.87.3. In my case I had some strategies registered with namedtuple types which started getting generated for unrelated strategies. It also happens for Sequence subclasses, but only if they are not specifying a generic type.

It seems to be related to #2951.

try_issubclass(k, thing) thinks the Thing namedtuple is a subclass of Sequence[Other].

I can see this is a rather hairy problem looking at the code!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementit's not broken, but we want it to be better

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions