Import a pyi (type stub file) into a normal python module
Asked Answered
F

2

12

I have a program (like a macro) that runs within a parent program and imports an API module from that program (lets call it foo). The problem is that that module only exists within that program, so I can't do things like run pydocmd outside the software because the script throws a ReferenceError. To aid in my own development I have create a type stub file, foo.pyi, in my project directory. What I would like to do is import that type stub as a normal Python file if the import fails, to provide dummy functions and properties. Something like:

try:
  import foo
except ImportError:
  from . import foo.pyi

This raises an error, however, as it's trying to import pyi from the foo library that does not exist in the project folder. The only other option I can think of is to have an identical copy of the .pyi file as, say "dummy_foo.py" but then I have to maintain two copies of the same file in one repo. I'd rather not do that.

Featherweight answered 14/5, 2019 at 16:10 Comment(3)
I'd also like to know how to do thisProtecting
can you elaborate a bit more on the stub file? Those are usually used for type-hinting, but your question makes it sound like you have actual logic in it? I have a fairly good idea on how to solve your question as long as I understood it correctly. I just want to make sure I've got it right before answering. It would help a TON if you could add an MRE to your question (also for future visitors).Rosabelle
Try https://mcmap.net/q/14785/-how-can-i-import-a-module-dynamically-given-the-full-pathDoucet
T
2

I wrote this a while back; should still work I think:

import importlib


def import_stub(stubs_path, module_name):
    sys.path_hooks.insert(0,
        importlib.machinery.FileFinder.path_hook(
            (importlib.machinery.SourceFileLoader, ['.pyi']))
    )
    sys.path.insert(0, stubs_path)
    
    try:
        return importlib.import_module(module_name)
    finally:
        sys.path.pop(0)
        sys.path_hooks.pop(0)
Troglodyte answered 22/6, 2022 at 20:23 Comment(0)
S
2

I found this question, but my problem was about type checking. In my case pyi file contains class definition (so type hints are working), but the library doesn't. Solution is in checking typing.TYPE_CHECKING:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from library import _PrivateClass

def foo(x: "_PrivateClass"):
    ...
Salpingitis answered 12/1, 2023 at 2:32 Comment(1)
from __future__ import annotations gives a nice way, see here.Yevetteyew

© 2022 - 2024 — McMap. All rights reserved.