Skip to content

Commit e4c5f08

Browse files
authored
fix(packaging): ship nat.plugin_api in nvidia-nat-core wheel (#1997)
Follow-up to #1959. The stable public plugin API module (`nat.plugin_api`) is not shipped in the `nvidia-nat-core` wheel, so `from nat import plugin_api` fails in fresh installs of the nightly build: ```console $ uv pip install --prerelease=allow "nvidia-nat-core==1.8.0a20260529" $ python -c "from nat import plugin_api" ImportError: cannot import name 'plugin_api' from 'nat' (unknown location) ``` The file is also absent from the wheel's `RECORD`. ### Root cause `nat` is a PEP 420 namespace package, and `packages/nvidia_nat_core/pyproject.toml` discovers contents via: ```toml [tool.setuptools.packages.find] where = ["src"] include = ["nat.*"] ``` `setuptools.packages.find` only enumerates **packages** (directories), never standalone top-level `.py` **modules**. `plugin_api.py` is the only top-level module under `nat/`, so it silently drops out of the wheel. Verified empirically with `find_namespace_packages(where='src', include=['nat.*'])` — returns 95 subpackages, none of which is `nat.plugin_api`. ### Fix Convert `packages/nvidia_nat_core/src/nat/plugin_api.py` → `packages/nvidia_nat_core/src/nat/plugin_api/__init__.py`. As a subpackage it is picked up by the existing `include = ["nat.*"]` rule with no `pyproject.toml` change. The import contract is unchanged for consumers — both `from nat import plugin_api` and `from nat.plugin_api import X` continue to work, and the test suite added in #1959 (`packages/nvidia_nat_core/tests/nat/test_plugin_api.py`) exercises these forms without modification. ### Verification ```bash cd packages/nvidia_nat_core uv build --wheel unzip -l dist/nvidia_nat_core-*.whl | grep plugin_api # -> nat/plugin_api/__init__.py ``` After install, `from nat import plugin_api` and `from nat.plugin_api import Builder` resolve. ## By Submitting this PR I confirm: - I am familiar with the [Contributing Guidelines](https://github.com/NVIDIA/NeMo-Agent-Toolkit/blob/develop/docs/source/resources/contributing/index.md). - We require that all contributors "sign-off" on their commits. This certifies that the contribution is your original work, or you have rights to submit it under the same license, or a compatible license. - Any contribution which contains commits that are not Signed-Off will not be accepted. - When the PR is ready for review, new or existing tests cover these changes. - When the PR is ready for review, the documentation is up to date with these changes. ## Summary by CodeRabbit * **Documentation** * Excluded the plugin-specific API package from autogenerated API docs to prevent duplicate or irrelevant entries in the published documentation. * Implemented this exclusion in the API-tree generation logic; no other documentation build setup changes were made. [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NeMo-Agent-Toolkit/pull/1997?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) Authors: - Bryan Bednarski (https://github.com/bbednarski9) Approvers: - David Gardner (https://github.com/dagardner-nv) URL: #1997
1 parent 59a4fde commit e4c5f08

2 files changed

Lines changed: 9 additions & 1 deletion

File tree

docs/source/conf.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,21 @@ def _build_api_tree() -> Path:
6363
with open(dest_dir / "__init__.py", "w", encoding="utf-8") as f:
6464
f.write("")
6565

66+
# Subpackages excluded from the generated API tree. ``nat.plugin_api`` is the public
67+
# plugin-author facade that re-exports symbols from their canonical modules; including it
68+
# here would register duplicate cross-reference targets (e.g. ``InvocationContext`` in both
69+
# ``nat.plugin_api`` and ``nat.middleware.middleware``) and trip the docs build's ``-W``.
70+
# TODO: once the docs are restructured to make ``nat.plugin_api`` the canonical reference
71+
# for plugin authors, remove this exclusion and invert the resolution direction.
72+
skip_from_api_docs = {"plugin_api"}
73+
6674
plugin_dirs = [Path(p) for p in glob.glob(f'{plugins_dir}/nvidia_nat_*')]
6775
for plugin_dir in plugin_dirs:
6876
src_dir = plugin_dir / 'src/nat'
6977
print(f"Copying {src_dir} to {dest_dir}")
7078
if src_dir.exists():
7179
for plugin_subdir in src_dir.iterdir():
72-
if plugin_subdir.is_dir():
80+
if plugin_subdir.is_dir() and plugin_subdir.name not in skip_from_api_docs:
7381
dest_subdir = dest_dir / plugin_subdir.name
7482
shutil.copytree(plugin_subdir, dest_subdir, dirs_exist_ok=True)
7583
package_file = dest_subdir / "__init__.py"
File renamed without changes.

0 commit comments

Comments
 (0)