def get_source(import_name: str) -> Optional[str]:
spec = get_spec(import_name)
# Now, here. The spec.loader might be one of several values.
# But I *know* that it is gonna be importlib.machinery.SourceFileloader
# I need to typecast the attribute of the spec.loader into the above
if spec and spec.loader.path.endswith('.py'):
return spec.loader.get_data(spec.loader.path).decode("utf-8")
return None
def get_spec(import_name: str) -> importlib.machinery.ModuleSpec:
try:
return importlib.util.find_spec(import_name)
except (ImportError, AttributeError, TypeError, ValueError):
return None
Apparently PEP526 allows what I'm trying to do with the most basic syntax imaginable
obj.attr: annotation
However apparently type checkers do not have to support this syntax as far as I can tell from Rossum's comment. And mypy gives the error Type cannot be declared in assignment to non-self attribute
.
Now, according to another issue I found on github on typeshed, you can do asserts to let mypy know the type that the object. Instead of typehitting.
assert isinstance(obj.attr, annotation)
However this, to me, feels wrong. I'm trying to use typing features if possible, and the project I'm trying to contribute uses mypy as their type checker.
The assert version that works but makes me hate myself is:
def get_source(import_name: str) -> Optional[str]:
spec = get_spec(import_name)
assert isinstance(spec.loader, importlib.machinery.SourceFileLoader)
assert isinstance(spec.loader.path, str)
if spec and spec.loader.path.endswith('.py'):
return spec.loader.get_data(spec.loader.path).decode("utf-8")
return None
Countless typeshed and mypy issues I've read didn't help, so I'm here.