I'm working on a library that currently supports Python 3.6+, but having a bit of trouble with how forward references are defined in the typing module in Python 3.6. I've setup pyenv on my local Windows machine so that I can switch between different Python versions at ease for local testing, as my system interpreter defaults to Python 3.9.
The use case here essentially is I'm trying to define a TypeVar with the valid forward reference types, which I can then use for type annotation purposes. I've confirmed the following code runs without issue when I'm on 3.7+ and import ForwardRef from the typing module directly, but I'm unable to get it on Python 3.6 since I noticed forward refs can't be used as arguments to TypeVar for some reason. I also tried passing the forward ref type as an argument to Union , but I ran into a similar issue.
Here are the imports and the definition forTypeVar that I'm trying to get to work on both python 3.6.0 as well as more recent versions like 3.6.8 - I did notice I get different errors between minor versions:
from typing import _ForwardRef as PyForwardRef, TypeVar
# Errors on PY 3.6:
# 3.6.2+ -> AttributeError: type object '_ForwardRef' has no attribute '_gorg'
# 3.6.2 or earlier -> AssertionError: assert isinstance(a, GenericMeta)
FREF = TypeVar('FREF', str, PyForwardRef)
Here is a sample usage I've been able to test out, which appears to type check as expected for Python 3.7+:
class MyClass: ...
def my_func(typ: FREF):
pass
# Type checks
my_func('testing')
my_func(PyForwardRef('MyClass'))
# Does not type check
my_func(23)
my_func(MyClass)
What I've Done So Far
Here's my current workaround I'm using to support Python 3.6. This isn't pretty but it seems to at least get the code to run without any errors. However this does not appear to type check as expected though - at least not in Pycharm.
import typing
# This is needed to avoid an`AttributeError` when using PyForwardRef
# as an argument to `TypeVar`, as we do below.
if hasattr(typing, '_gorg'): # Python 3.6.2 or lower
_gorg = typing._gorg
typing._gorg = lambda a: None if a is PyForwardRef else _gorg(a)
else: # Python 3.6.3+
PyForwardRef._gorg = None
Wondering if I'm on the right track, or if there's a simpler solution I can use to support ForwardRef types as arguments to TypeVar or Union in Python 3.6.