Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to determine if run/imported by pdoc at runtime? #449

Open
lovetheguitar opened this issue Nov 4, 2022 · 8 comments
Open

Comments

@lovetheguitar
Copy link

We have to deal with C# dlls and have some wrapper objects around those.

When run with pdoc we'd like to mock these objects to get descriptive documentation.

Is there a some environment variable or anything set by pdoc that would give us this information, e.g. like if TYPE_CHECKING.

Currently we are catching import errors and replacing it with mocks, which gives us nice documentation, but in case a dll is missing we loose valuable tracebacks.

Thanks a lot for maintaining this lovely piece of code. 😸

@lovetheguitar lovetheguitar changed the title Is there a way in code to determine if run/imported by pdco? Is there a way to determine if run/imported by pdoc at runtime? Nov 4, 2022
@mhils
Copy link
Member

mhils commented Nov 4, 2022

I'm not sure if I understand what exactly your problem is. You want to detect if pdoc is running during import, is that correct?

If you have some weird import quirks, my general recommendation would be to write a Python script where you first do whatever you need to do for your imports to work, and then call pdoc programatically: https://github.com/mitmproxy/pdoc/blob/main/examples/library-usage/make.py

@lovetheguitar
Copy link
Author

I'm using pdoc only via command line and would like to keep it that way very much.

I have code like this:

try:
    from msl import loadlib

    for dll_name in _REQUIRED_DLLS:
        dll_path = PACKAGE_BIN_DIRECTORY / dll_name
        if not dll_path.exists:
            raise DllError(f'Dependency "{dll_path}" not found')
        loadlib.LoadLibrary(str(dll_path), "net")
    del dll_name, dll_path
    from Drivers import (  # noqa: E402
        MeasurementEquipment as _MeasurementEquipment,
    )
    from HP3458 import HP3458 as _HP3458  # noqa: E402
except ModuleNotFoundError:
    warnings.warn(
        "Could not load dlls"
        RuntimeWarning,
    )
    # The documentation is built on Ubuntu, therefore we need to mock the imports of the dll stuff.
    _HP3458 = mock.MagicMock()
    _MeasurementEquipment = mock.MagicMock()

I'd like to improve this to something like

if os.environ["PDOC_DOCUMENTATION_RUN"] == "True":
    _HP3458 = mock.MagicMock()
    _MeasurementEquipment = mock.MagicMock()
else:
    from msl import loadlib

    for dll_name in _REQUIRED_DLLS:
        dll_path = PACKAGE_BIN_DIRECTORY / dll_name
        if not dll_path.exists:
            raise DllError(f'Dependency "{dll_path}" not found')
        loadlib.LoadLibrary(str(dll_path), "net")
    del dll_name, dll_path
    from Drivers import (  # noqa: E402
        MeasurementEquipment as _MeasurementEquipment,
    )
    from HP3458 import HP3458 as _HP3458  # noqa: E402

@mhils
Copy link
Member

mhils commented Nov 4, 2022

You could just set an env var and then run pdoc? If you are on Linux, that'd be

PDOC_DOCUMENTATION_RUN=1 pdoc ...

@lovetheguitar
Copy link
Author

lovetheguitar commented Nov 4, 2022

Then I'd have to set and unset this variable any time I wanted to see/build the documentation or use the application/run tests on it.

I was thinking about something similar to this in pytest https://docs.pytest.org/en/7.1.x/example/simple.html#detect-if-running-from-within-a-pytest-run
or https://docs.pytest.org/en/7.1.x/example/simple.html#pytest-current-test-environment-variable.

Maybe there is some other, more elegant way that would accomplish that?

Thanks a lot for for your help. 😺

@mhils
Copy link
Member

mhils commented Nov 5, 2022

Maybe there is some other, more elegant way that would accomplish that?

I personally would use an environment variable as it makes things relatively clean, but if you are so inclined you can of course also do import sys; if "pdoc" in sys.modules: ...

@lovetheguitar
Copy link
Author

Would you be open to a PR adding that functionality, correctly setting & unsetting such an environment variable, and documenting it?

@mhils
Copy link
Member

mhils commented Nov 10, 2022

I don't have a particular strong opinion here, but this feels very much like an edge case that doesn't warrant extra complexity in pdoc itself. I'm trying hard to not replicate Sphinx in terms of configurability, and this just may not pass the bar. If we find that more folks are chiming in here I'm more than willing to reconsider though. :)

@jeinstei
Copy link

I actually have this exact problem when building documentation on Linux for a module designed to run using ctypes.WinDLL on windows. I currently have something like the code below, but I'm not a huge fan of it.

# Check the platform to allow for
plat = platform.platform()
if "Windows" not in plat:
    msg = "%s can't import WinDLL -- abstracting away for documentation purposes" % plat
    LOG.error(msg)
    ctypes.WinDLL = object
    import sys
    if not "pdoc" in sys.modules:
        raise EnvironmentError(msg)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants