django-stubs
django-stubs copied to clipboard
support for psycopg 3 `Range` types in `django.contrib.postgres.fields.ranges`
In django.contrib.postgres.fields.ranges the Range types are imported from psycopg2, which has been superseded by psycopg 3:
https://github.com/typeddjango/django-stubs/blob/2446b523d5caee05dc064805216a07f03e8d828d/django-stubs/contrib/postgres/fields/ranges.pyi#L9
the types-psycopg2 typeshed stubs package could help with the # type: ignore, btw
The range fields use the psycopg2 Range type as upper bound for the generic type parameters of the range fields:
https://github.com/typeddjango/django-stubs/blob/2446b523d5caee05dc064805216a07f03e8d828d/django-stubs/contrib/postgres/fields/ranges.pyi#L28-L30
Ok, so what's the problem?
So I'm not able to use the psycopg 3 psycopg.types.range.Range as type argument here. Note that _RangeT has no default, so I'm required to pass a type argument here.
Working around it
The least invalid workaround would be to pass Any as type argument. But if you don't mind getting your hands dirty, you could also ignore the upper bound, and throw some of those # type: ignore[misc] and/or # pyright: ignore[reportVerboseDescriptionOfAnErrorThatCouldAlsoBeWrittenInOneWOrd] onto it, and it'll probably work regardless.
And I hate to say it, so please forgive me for putting it in such strong terms, but I consider both workarounds to be suboptimal.
Why it's impossible to solve, and some possible solutions.
That's, well, not possible... Or at least, not if you want to support both psycopg2 and psycopg 3. Because try: import ... isn't a thing in stubs, unfortunately.
However, it looks like both Range types from v2 and v3 are structurally equivalent. So another option would be to copy-paste the typeshed code of Range, swap the Generic for a Protocol, and voilà.
Another option would be to just get rid of the _RangeT upper bound altogether.
Covariance, maybe?
Since _RangeT only annotates range_type: type[_RangeT], and assuming that it's intended as a read-only attribute, perhaps it makes sense to slap a _co on the _RangeT?