◐ Shell
clean mode source ↗

feat: add scyjava-stubgen cli command, and `scyjava.types` namespace, which provide type-safe imports with lazy init by tlambert03 · Pull Request #82 · scijava/scyjava

@ctrueden @claude

Stubs are placed in the scyjava.types namespace by default,
but have imports with a toplevel namespace; for example,
when generating stubs for org.scijava:scijava-common, the file:

    src/scijava/types/org/scijava/__init__.pyi

would declare imports:

    import java.lang
    import java.util

    import org.scijava.annotations
    import org.scijava.app
    import org.scijava.cache
    import org.scijava.command

and so on. But these imports yield errors when browsing in an IDE,
and prevent the type checker from resolving all the types properly.

This commit makes the following changes to address the problem:

- Add a python_package_prefix parameter to generate_stubs() function
- Add a _rewrite_stub_imports() function that:
  - Rewrites import foo.bar.X → import {python_package_prefix}.foo.bar.X
  - Rewrites type references similarly to have the python_package_prefix
- Update the CLI to automatically pass
  python_package_prefix="scyjava.types" when using the default location
- If --output-python-path gives a different prefix, use that instead
- Add a new test_stubgen_type_references to validate rewriting behavior

So then the following example above gets rewritten to be:

    import java.lang
    import java.util

    import scyjava.stubs.org.scijava.annotations
    import scyjava.stubs.org.scijava.app
    import scyjava.stubs.org.scijava.cache
    import scyjava.stubs.org.scijava.command

Note that the java.lang and java.util imports are not rewritten,
because they are not among the classes whose stubs are being generated.

With this change, IDEs now autocomplete expressions involving these Java
classes correctly, even when chained; for example:

    import scyjava.stubs.org.scijava.Context

    Context().getServiceIndex().getA

shows getAll as a valid completion, because getAll() is a member method
of a supertype of ServiceIndex, the class returned by getServiceIndex().
Before this patch, such chained type completions did not work.

Co-authored-by: Claude <noreply@anthropic.com>