Skip to content

Conversation

@chadrik
Copy link
Contributor

@chadrik chadrik commented Apr 5, 2025

Description

Add python stub files for code completion and static analysis.

Fixes #4682

Tests

No new test cases, since there is not any change to the behavior. I do have an idea for a kind of test that might validate the stubs against the python unit tests, but I don't know if it's worth it.

Checklist:

  • I have read the contribution guidelines.
  • I have updated the documentation, if applicable. (Check if there is no
    need to update the documentation, for example if this is a bug fix that
    doesn't change the API.)
  • I have ensured that the change is tested somewhere in the testsuite
    (adding new test cases if necessary).
  • If I added or modified a C++ API call, I have also amended the
    corresponding Python bindings (and if altering ImageBufAlgo functions, also
    exposed the new functionality as oiiotool options).
  • My code follows the prevailing code style of this project. If I haven't
    already run clang-format before submitting, I definitely will look at the CI
    test that runs clang-format and fix anything that it highlights as being
    nonconforming.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Apr 5, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

Copy link
Contributor Author

@chadrik chadrik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are my takeaways from this effort:

  1. While std::optional is generally a win in terms of reducing the need for maintaining manual fixes to the stubs, there are many other scenarios where we cannot pass enough information through to pybind11 to guide the stubgen process via C++, such as unbounded tuples (tuple[T, ...] vs tuple[A, B, C]) or type unions (T | list[T] | tuple[T, ...]). If we want good stubs then we're signing up for permanantly maintaining these manual corrections external to our C++ code.
  2. While I was hoping to publish a separate types-OpenImageIO with just the stubs, it will have a snowball effect on the CI build and release process, so for now I'd like to set a simpler goal of adding the __init__.pyi file to the existing OpenImageIO distribution.

@chadrik
Copy link
Contributor Author

chadrik commented Apr 5, 2025

Idea: modifying py_to_stdvector to use std::variant could be a big win for adding more type transparency to drive more of the stub types from C++.

@chadrik
Copy link
Contributor Author

chadrik commented Apr 10, 2025

Here's a progress report.

  • The stub generator python script needs to have its deps installed. Using a PEP 723 runner lets us avoid the complication of creating a one-off virtual environment to run the script and install its deps, but only if we have a PEP 723 compatible runner installed, such as uv or pipx. There are 3 contexts where we need to ensure uv or pipx is installed: local builds, ci wheel builds, ci library builds. Unfortunately, for local builds, we have to choose between documenting that users must install uv or installing it automatically, which puts us back at writing cmake code to create a virtual env.
  • The stub generator needs to import the built OpenImageIO python library to inspect it. I had to rearrange where the bindings are stored during the build process so that the __init__.py is present when the stub generator imports it because it has some extra logic to handle Windows weirdness. It's still failing to import on Windows.

Stepping back a bit, one of our goals for adding stub generation to this repo is to create a tight feedback loop between changes to C++ and the resulting stubs. With this goal in mind, I set out to add the stub generation process to the cmake build script, in the hopes that, by making stubs every time that the python bindings were built, developers could easily discover the result of their changes. However, I'm realizing that this exposes us to a lot of complication in CI. It feels complex and brittle to have to build the stubs on every platform and python version (ensuring that uv is installed everywhere, ensuring that the bindings are importable during the cmake build process) when the resulting stub file is the same for every platform and version of python. In theory we could build the stubs just once on a trusted platform and python version and publish the stubs separately as a types-OpenImageIO python distribution.

Another problem is that there's nothing that forces a developer to review the effects of their C++ changes on the stubs, so while my current design succeeds at creating a tighter feedback loop between C++ and stubs, changes are likely to go unnoticed.

Here's an idea for a solution to this problem:

  • commit the __init__.pyi stub to the repo (vs generating it on the fly)
  • add a manually run script that updates the stub file (vs running it every build)
  • add a CI job that runs the stub generation and raises an error if it's different from what's committed in the repo. this forces the developer to re-run the stub generator locally and commit their results. this in turn means that any regressions introduced by their changes will be exposed in the review process

@lgritz
Copy link
Collaborator

lgritz commented Apr 12, 2025

@zachlewis and other heavy Python users, can you keep an eye on this PR and provide feedback? I've never generated (or even used) these stub files, so I don't feel qualified to pass any judgment on it.

@zachlewis
Copy link
Collaborator

In theory we could build the stubs just once on a trusted platform and python version and publish the stubs separately as a types-OpenImageIO python distribution.

This may be the cleanest and simplest thing to do; and, like you mentioned earlier, it allows for type-checking in extremely light environments. Ostensibly, we could even run a building and publishing step for the types-OpenImageIO package immediately after publishing the OpenImageIO package, assuming we're not too quick for pypi.

Alternatively, if we limit our scope to only generating stubs when building wheels with cibuildwheel, perhaps we could exploit CIBW's "repair-wheel" step; i.e., we'd invoke a custom script that:

  1. repairs the wheels
  2. runs the stub generation script with the PEP 723 OpenImageIO dependency pointing to the relative location of the repaired wheels
  3. properly patches the init.pyi stub into the .whl

Here's an idea for a solution to this problem:

- commit the __init__.pyi stub to the repo (vs generating it on the fly)
- add a manually run script that updates the stub file (vs running it every build)

I like this, too. There's something to be said for not attempting to be too clever about all this. We can simply say, "If you're updating the Python bindings, make sure to run the script that generates new stubs". If it makes things easier for folks, we could even expose a stub-generating script as part of the OpenImageIO package itself.

@zachlewis
Copy link
Collaborator

I messed around with the cibuildwheel "repair-wheel" step hack as described above... I haven't tested on windows, but it seems like it's doing what it's supposed to be doing at first glance...

If you're interested, I posted a proof of concept here:
https://gist.github.com/zachlewis/67ee0a8faae8c25240d8fbaf315bd7e1

@chadrik chadrik force-pushed the python-stubgen branch 4 times, most recently from 3e6e675 to 6258dd3 Compare April 20, 2025 15:04
@lgritz lgritz added the python Python APIs label Apr 21, 2025
@chadrik
Copy link
Contributor Author

chadrik commented Apr 22, 2025

I messed around with the cibuildwheel "repair-wheel" step hack as described above... I haven't tested on windows, but it seems like it's doing what it's supposed to be doing at first glance...

If you're interested, I posted a proof of concept here: https://gist.github.com/zachlewis/67ee0a8faae8c25240d8fbaf315bd7e1

Thanks for the great suggestion @zachlewis. I had a look and it gave me some ideas to improve my approach. After some consideration, I think test-command will be better for my case than repair-wheel-command because the repair command is actively used and has defaults that vary per OS -- I don't want to accidentally break anything. The test-command actually works a lot like a "post-build callback", so it seems like a good fit.

Have a look at the current state of things. I'm happy with where things landed.

These are the requirements I was trying to hit when designing this workflow:

  • DO NOT complicate the default build process: the stubs represent a niche artifact and we don't want it causing failures for folks during day to day development. The new workflow only runs during local development if explicitly called via make pystubs
  • notify developers if the changes in their PR will result in a change to the stubs. I don't want to opaquely auto-generate stubs in CI and blindly shuttle them into a wheel. I want developers to know when their C++ change results in a degradation of the stubs, so that they can go through a review process, and the generate_stubs rules can be updated to accommodate.
  • install stubs automatically when pip install OpenImageIO is run. We don't want developers to have to know to install this or else many people will miss out on this quality of life improvement. I'm including the stub within every wheel distribution.

I left two goals for later PRs:

  • create a wheel that can be installed separately from the C-extension wheels, to keep lightweight environments.
  • modify the python bindings to avoid obscuring types (e.g. using modern C++ types like std::optional

@chadrik chadrik force-pushed the python-stubgen branch 2 times, most recently from 1dfa3f4 to e5150f7 Compare April 22, 2025 14:46
@chadrik
Copy link
Contributor Author

chadrik commented Apr 29, 2025

@zachlewis @lgritz This is ready for review. I've removed the C++ changes, so I think what I have is quite safe. It would be good to test out the local workflows on a platform other than MacOS, which is what I'm using.

@zachlewis
Copy link
Collaborator

This is fantastic. Just a couple of questions inline, but I'm quite happy with everything you've put together. Thank you! This was quite an effort, and I appreciate the time you put into making stub generation as simple as possible to slot into OIIO's existing CI workflows. I'd definitely like to do something similar for OCIO!

@cdombrova-scanlinevfx
Copy link

@zachlewis did you have some comments you were going to add? Maybe you forgot to complete the review?

Now that we’ve got a workflow design for this that show work for C++ projects I doubt it would be much work to add this to OCIO.

@lgritz
Copy link
Collaborator

lgritz commented May 13, 2025

There seems to be a commit with missing DCO.

Aside from that, where do we stand on this? I'm not enough of a Python power user or native speaker to really judge it. What say you, @zachlewis? Is this complete as far as you're concerned, @chadrik?

# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO

from __future__ import annotations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, at which Python version is the annotations stuff included and no longer needs to come from __future__?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed once OCIO drops support for python 3.9, and only supports 3.10+

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that will be a while. I think for 3.1 (~Sept release), we will probably raise our minimum from 3.7 to 3.9. But I think we can't go beyond that. Even at my company, I anticipate needing active 3.9 support through the end of the calendar year to be safe.

Copy link
Contributor Author

@chadrik chadrik May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The longer answer is that there are ways to avoid adding this import, but IMHO they are not worth the effort. For example, if you commit to using typing.List[X] instead of list[str], and using typing.Union[X, Y] instead of X | Y. It's (understandably) difficult for people to keep track of which version introduced which feature, so using from __future__ import annotations is a catchall that lets us not care so we can use these newer features even in python 3.7.

Copy link
Collaborator

@lgritz lgritz May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I'm not worried about the import being there at all. It was mostly a curiosity of when in the future we need to remember that they are no longer needed.



def print_deep_imagebuf (buf, prefix) :
def print_deep_imagebuf (buf: oiio.ImageBuf, prefix: str) :
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to mostly-self: we should remember to take a pass over the docs and any python examples in the docs and change all the function declarations to use modern python3 syntax with type annotations.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added this: #4752

Comment on lines +1 to +4
#
# This file is auto-generated. DO NOT MODIFY! Run `make pystubs` to regenerate
#

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with checking this into the repo, but do we have an automated way to detect that something has changed about the python bindings in a way that necessitates a re-generation? Should we add a note to the RELEASING.md guide reminding us to regenerate on every release as part of the release staging process?

Copy link
Contributor Author

@chadrik chadrik May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a developer changes anything in the code that results in the type stubs changing, the cp311-manylinux_x86_64
and cp311-manylinux_aarch64 wheel build jobs in CI will fail, and it will print a diff and the instructions on how to update the stubs. I also updated the INSTALL.md with the instructions on how to update the stubs.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, good enough

chadrik added 2 commits May 13, 2025 17:04
Signed-off-by: Chad Dombrova <chadrik@gmail.com>
Signed-off-by: Chad Dombrova <chadrik@gmail.com>
@chadrik
Copy link
Contributor Author

chadrik commented May 14, 2025

Yes, I think this is ready to go. I've also started porting this workflow over to OCIO.

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

OK, I'd love to just get a very last ok from Zach, then I'm ready to merge.

@zachlewis
Copy link
Collaborator

What say you, @zachlewis?

I think everything about this PR is fantastic.

@chadrik
Copy link
Contributor Author

chadrik commented May 14, 2025

One last question: is it worth cherry-picking this onto other release branches, so that folks can benefit from this even if they're stuck on older versions? If yes, would I introduce an MR for each release branch?

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

One last question: is it worth cherry-picking this onto other release branches, so that folks can benefit from this even if they're stuck on older versions? If yes, would I introduce an MR for each release branch?

I was planning to backport to 3.0, the currently supported release family. You don't need to do it. All new code goes into main, and I cherry-pick the things that look like they can safely merge into the release branch and make sure CI verifies that they don't break anything.

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

BTW, don't worry about the failing "bleeding edge" test. That is the test that builds against top-of-tree of several of our dependencies, and it frequently breaks when dependencies change or momentarily introduce bugs on their side. It looks like something changed in freetype today that is responsible. I'll let that keep failing for a few days to see if it's just a freetype regression that they fix on their own.

@lgritz lgritz merged commit e787dc6 into AcademySoftwareFoundation:main May 14, 2025
69 of 70 checks passed
lgritz pushed a commit to lgritz/OpenImageIO that referenced this pull request May 14, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

@chadrik I tried cherry-picking into dev-3.0 but it fails (you were right about it catching changes!) because the stubs aren't quite right and need to be built separately for that branch. I tried the make pystubs but actually had some trouble (on my Mac laptop). It's probably something about my setup, but I don't have time to track it down.

So I'd like to request two things from you, if you don't mind:

  1. On your end (and in your fork), please cherry pick into dev-3.0, regen the stubs, and then submit the combo as a PR against dev-3.0 and I'll do that merge.
  2. Anticipating that this may come up in the future, not just for me but possibly others, I'm thinking that a good strategy might be to modify the check so that if it fails, it should generate new stubs (can it do that reliably from CI?) and save it as an artifact, so that from the GH page showing the test failure, the user who submitted the PR can download the file, inspect it, and add it to their PR even if they didn't have the capacity to generate it on their end. (This is basically mimicking our "clang-format" test, which when it fails, allows people to download the diffs to apply on their end even if it's not possible for them to actually run "clang-format" with the right version on their own machine.)

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

@chadrik Not a huge rush on this, BTW. I think we are just aiming to be able to cherry-pick it into dev-3.0 successfully before the next scheduled release from that branch, on June 1.

@cdombrova-scanlinevfx
Copy link

Yeah, that all seems reasonable.

If you have a chance to post your error I’d love to check it out. I’d like to make it more bulletproof.

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

Sure. Here's what happened for me. Keep in mind I have some unclean set of multiple pythons, whatever is on the system, whatever homebrew installed, etc.

$ make pystubs
[1/2] pystubs: Generating python stubs
FAILED: wheelhouse/OpenImageIO/__init__.pyi /Users/lg/code/oiio/oiio.lg/build/wheelhouse/OpenImageIO/__init__.pyi
cd /Users/lg/code/oiio/oiio.lg/build/src/python/stubs && /usr/local/Frameworks/Python.framework/Versions/3.13/bin/python3.13 /Users/lg/code/oiio/oiio.lg/src/python/stubs/generate_stubs_local.py --repo-root /Users/lg/code/oiio/oiio.lg --python-version="3.11" --cibuildwheel-version="2.21.1" --output-dir /Users/lg/code/oiio/oiio.lg/build/wheelhouse
Installed 7 packages in 11ms

     _ _       _ _   _       _           _
 ___|_| |_ _ _|_| |_| |_ _ _| |_ ___ ___| |
|  _| | . | | | | | . | | | |   | -_| -_| |
|___|_|___|___|_|_|___|_____|_|_|___|___|_|

cibuildwheel version 2.21.1

Build options:
  platform: linux
  allow_empty: False
  architectures: aarch64, i686, ppc64le, s390x, x86_64
  build_selector:
    build_config: cp311-manylinux_x86_64
    skip_config:
    requires_python: >=3.8
    prerelease_pythons: True
    free_threaded_support: True
  output_dir: /Users/lg/code/oiio/oiio.lg/build/wheelhouse
  package_dir: /Users/lg/code/oiio/oiio.lg
  test_selector:
    skip_config:
  before_all:
  before_build:
  before_test:
  build_frontend: None
  build_verbosity: 1
  config_settings:
  container_engine: docker
  dependency_constraints: pinned
  environment:
    SKBUILD_CMAKE_ARGS="-DLINKSTATIC=1"
    CXXFLAGS="-Wno-error=stringop-overflow -Wno-pragmas"
    SKBUILD_CMAKE_BUILD_TYPE="MinSizeRel"
  manylinux_images:
    x86_64: quay.io/pypa/manylinux2014_x86_64:2024.09.16-1
    i686: quay.io/pypa/manylinux2014_i686:2024.09.16-1
    pypy_x86_64: quay.io/pypa/manylinux2014_x86_64:2024.09.16-1
    aarch64: quay.io/pypa/manylinux2014_aarch64:2024.09.16-1
    ppc64le: quay.io/pypa/manylinux2014_ppc64le:2024.09.09-0
    s390x: quay.io/pypa/manylinux2014_s390x:2024.09.09-0
    pypy_aarch64: quay.io/pypa/manylinux2014_aarch64:2024.09.16-1
    pypy_i686: quay.io/pypa/manylinux2014_i686:2024.09.16-1
  musllinux_images:
    x86_64: quay.io/pypa/musllinux_1_2_x86_64:2024.09.16-1
    i686: quay.io/pypa/musllinux_1_2_i686:2024.09.16-1
    aarch64: quay.io/pypa/musllinux_1_2_aarch64:2024.09.09-0
    ppc64le: quay.io/pypa/musllinux_1_2_ppc64le:2024.09.09-0
    s390x: quay.io/pypa/musllinux_1_2_s390x:2024.09.09-0
  repair_command: auditwheel repair -w {dest_dir} {wheel}
  test_command:
    *: oiiotool --buildinfo
    cp311-manylinux_x86_64: oiiotool --buildinfo && python {project}/src/python/stubs/generate_stubs.py --out-path '/output' --validate-path '{project}/src/python/stubs/OpenImageIO/__init__.pyi'
  test_extras:
  test_requires:
    *:
    cp311-manylinux_x86_64:
      mypy~=1.15.0
      stubgenlib~=0.1.0

Cache folder: /Users/lg/Library/Caches/cibuildwheel

Here we go!

Traceback (most recent call last):
  File "/Users/lg/.cache/uv/archive-v0/UlJa7mfI6eeKXlO_lDHv5/bin/cibuildwheel", line 12, in <module>
    sys.exit(main())
             ~~~~^^
  File "/Users/lg/.cache/uv/archive-v0/UlJa7mfI6eeKXlO_lDHv5/lib/python3.13/site-packages/cibuildwheel/__main__.py", line 49, in main
    main_inner(global_options)
    ~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/Users/lg/.cache/uv/archive-v0/UlJa7mfI6eeKXlO_lDHv5/lib/python3.13/site-packages/cibuildwheel/__main__.py", line 184, in main_inner
    build_in_directory(args)
    ~~~~~~~~~~~~~~~~~~^^^^^^
  File "/Users/lg/.cache/uv/archive-v0/UlJa7mfI6eeKXlO_lDHv5/lib/python3.13/site-packages/cibuildwheel/__main__.py", line 352, in build_in_directory
    platform_module.build(options, tmp_path)
    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
  File "/Users/lg/.cache/uv/archive-v0/UlJa7mfI6eeKXlO_lDHv5/lib/python3.13/site-packages/cibuildwheel/linux.py", line 434, in build
    subprocess.run(
    ~~~~~~~~~~~~~~^
        [build_step.container_engine.name, "--version"],
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        check=True,
        ^^^^^^^^^^^
        stdout=subprocess.DEVNULL,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/Cellar/python@3.13/3.13.3/Frameworks/Python.framework/Versions/3.13/lib/python3.13/subprocess.py", line 554, in run
    with Popen(*popenargs, **kwargs) as process:
         ~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.13/3.13.3/Frameworks/Python.framework/Versions/3.13/lib/python3.13/subprocess.py", line 1039, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                        pass_fds, cwd, env,
                        ^^^^^^^^^^^^^^^^^^^
    ...<5 lines>...
                        gid, gids, uid, umask,
                        ^^^^^^^^^^^^^^^^^^^^^^
                        start_new_session, process_group)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/python@3.13/3.13.3/Frameworks/Python.framework/Versions/3.13/lib/python3.13/subprocess.py", line 1969, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'docker'
Building cp311-manylinux_x86_64
Traceback (most recent call last):
  File "/Users/lg/code/oiio/oiio.lg/src/python/stubs/generate_stubs_local.py", line 62, in <module>
    main()
    ~~~~^^
  File "/Users/lg/code/oiio/oiio.lg/src/python/stubs/generate_stubs_local.py", line 43, in main
    subprocess.check_call(
    ~~~~~~~~~~~~~~~~~~~~~^
        [
        ^
    ...<9 lines>...
        cwd=args.repo_root,
        ^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/Cellar/python@3.13/3.13.3/Frameworks/Python.framework/Versions/3.13/lib/python3.13/subprocess.py", line 419, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['uv', 'tool', 'run', '--python=/usr/local/opt/python@3.13/bin/python3.13', 'cibuildwheel@2.21.1', '--output-dir=/Users/lg/code/oiio/oiio.lg/build/wheelhouse', '--only=cp311-manylinux_x86_64', '.']' returned non-zero exit status 1.
ninja: build stopped: subcommand failed.
make: *** [pystubs] Error 1
        3.05 real         1.06 user         0.37 sys

@lgritz
Copy link
Collaborator

lgritz commented May 14, 2025

Oh yeah, this part sure isn't going to work on my mac:

FileNotFoundError: [Errno 2] No such file or directory: 'docker'

lgritz pushed a commit to lgritz/OpenImageIO that referenced this pull request May 14, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
lgritz pushed a commit to lgritz/OpenImageIO that referenced this pull request May 15, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
scott-wilson pushed a commit to scott-wilson/OpenImageIO that referenced this pull request May 17, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
Signed-off-by: Scott Wilson <scott@propersquid.com>
scott-wilson pushed a commit to scott-wilson/OpenImageIO that referenced this pull request May 18, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
Signed-off-by: Scott Wilson <scott@propersquid.com>
zachlewis pushed a commit to zachlewis/OpenImageIO that referenced this pull request Aug 1, 2025
Add python stub files for code completion and static analysis.

Fixes
AcademySoftwareFoundation#4682

No new test cases, since there is not any change to the behavior. I do
have an idea for a kind of test that might validate the stubs against
the python unit tests, but I don't know if it's worth it.

---------

Signed-off-by: Chad Dombrova <chadrik@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Python APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE REQUEST] Python Stubs for Type Checking and Completion

5 participants