Convenience wrapper distribution for NeMo Platform Python packages
Project description
nemo-platform
Wrapper distribution for NeMo Platform. When users run pip install nemo-platform[services], this is the wheel they get.
The wheel bundles the SDK, shared runtime packages, default first-party plugins, and services directly from source via hatch force-include. As sub-packages are published independently to PyPI, they'll be removed from the bundle and added as normal dependencies instead.
How bundling works
All source bundling is configured in pyproject.toml via [tool.bundle-package]. Each entry declares a package source tree to include in the wheel:
[tool.bundle-package]
nemo-platform-plugin = { source = "../../packages/nemo_platform_plugin/src/nemo_platform_plugin", module = "nemo_platform_plugin" }
nemo-platform-sdk = { source = "../../sdk/python/nemo-platform/src/nemo_platform", module = "nemo_platform", inherit = { "optional-dependencies" = true, scripts = true } }
nemo-auditor-plugin = { source = "../../plugins/nemo-auditor/src/nemo_auditor", module = "nemo_auditor", inherit = { "entry-points" = ["nemo.*"] } }
nmp-auth = { source = "../../services/core/auth/src/nmp/core/auth", module = "nmp/core/auth", deps_group = "auth-service" }
Each entry has:
- key — the distribution/package name used to find its
pyproject.toml, read its metadata, and match wheelRequires-Distentries - source — relative path to the source directory to include in the wheel
- module — target module path inside the wheel
- deps_group (optional) — name of the
[project.optional-dependencies]group where the package's transitive deps are written. Defaults to the bundle key. - inherit (optional) — structured metadata to re-export from the bundled package. Supported keys are
scripts,entry-points, andoptional-dependencies; each value is eithertrueor a list of wildcard patterns. - scripts (optional) — explicit CLI entrypoints to register on the wrapper. Prefer
inherit.scriptswhen copying scripts from the bundled package. - force_include (optional) — extra source files, directories, or globs to bundle with this package, keyed relative to the entry's
sourcepath and mapped to their target wheel path. When using a glob, make the target end in/to copy each match into that package directory.
By default, bundled package metadata is not re-exported. nemo-platform opts into SDK scripts and SDK optional dependencies, and it opts into only nemo.* entry-point groups from the default first-party plugins. Other plugin entry-point groups, such as data_designer.plugins, are intentionally not inherited.
Two tools read this config:
hatch_build.py (build hook)
At wheel build time, hatch_build.py reads [tool.bundle-package] and generates hatch force-include mappings dynamically, including each entry's per-bundle force_include mappings. Component-owned runtime assets such as Alembic migrations and Studio UI static files should live on the corresponding bundle entry. The hook still merges any static [tool.hatch.build.targets.wheel.force-include] entries when present, but per-bundle force_include is preferred for assets owned by a bundled component.
During editable installs (uv sync), the build hook does nothing. Workspace packages resolve via their normal editable/workspace installation, so there is no copied bundle and the source dependency graph stays intact.
After the wheel is built, the build hook opens the wheel, rewrites METADATA, regenerates RECORD, and repacks the wheel. Any Requires-Dist whose distribution name matches a [tool.bundle-package] key is rewritten to a self-referencing extra using that entry's deps_group, or the bundle key when deps_group is omitted. Existing requirement extras and environment markers are preserved.
For example, this source dependency:
Requires-Dist: nmp-common
becomes this in the final wheel metadata:
Requires-Dist: nemo-platform[nmp-common]
A dependency with extras and a marker, such as nemo-platform-sdk[aiohttp] ; python_version >= "3.11", becomes nemo-platform[nemo-platform-sdk,aiohttp] ; python_version >= "3.11".
make vendor (vendor tool)
The vendor tool resets generated wrapper metadata before rebuilding it, so stale generated extras, scripts, and entry-point tables do not persist across runs. Generated sections are annotated with # Generated from [tool.bundle-package]; do not edit by hand..
The _process_bundle_packages() phase in vendor_package.py reads [tool.bundle-package] from every workspace package that has one. For each entry it:
- Finds the bundled package's
pyproject.toml, using the configuredsourcepath when needed - Reads its
[project.dependencies] - Filters out workspace packages that are not bundled by the parent, because they are not installable from PyPI
- Keeps bundled workspace dependency names readable in source metadata, so the wheel build hook can rewrite final
Requires-Distmetadata to self-extras - Writes the resulting deps into the generated extra named by
deps_group, or by the bundle key whendeps_groupis omitted - Copies only the metadata explicitly selected by
inherit - Writes any explicit
scripts = [...]declared directly on the bundle entry
For the wrapper specifically, make vendor also creates aggregate extras from [tool.bundle-package]:
core-servicereferences all core service*-serviceextras.pluginsreferences all bundled first-party plugin extras whose source lives underplugins/*/src.servicesreferencescore-service, all non-core service*-serviceextras, andplugins.
Dependency groups
The wrapper's [project.dependencies] is hand-written with the true workspace dependencies for the base install:
dependencies = [
"nemo-platform-sdk",
"nmp-common",
"nemo-platform-plugin",
]
Those direct workspace dependencies are what editable installs and repo-local tooling see. Wheel builds rewrite them to self-referencing extras so published wheels do not require unpublished workspace packages:
dependencies = [
"nemo-platform[nemo-platform-sdk]",
"nemo-platform[nmp-common]",
"nemo-platform[nemo-platform-plugin]",
]
Service and plugin dependencies are behind optional extras. They are composed via:
auth-service,entities-service, etc. — individual service depscore-service— aggregates all core service-serviceextrasplugins— aggregates default first-party plugin extrasservices— aggregatescore-service, all non-core service-serviceextras, andplugins
The services extra includes plugins because Python entry points are distribution-level metadata and are not conditional on extras. If the wrapper publishes plugin nemo.services entry points, installing service discovery dependencies must also install the plugin dependencies needed by those entry points.
The [project.optional-dependencies] section is auto-generated by make vendor. Do not edit it by hand. The wheel rewrite step assumes those generated deps_group extras already exist before the build starts.
The wrapper's generated [project.scripts] currently re-exports only the SDK CLI entry points:
[project.scripts]
nemo = "nemo_platform.cli.app:cli"
nmp = "nemo_platform.cli.app:cli"
Service-specific server scripts are not exposed by the umbrella nemo-platform wheel. Individual service packages may still expose their own scripts, and the wrapper uses nemo services run through the platform runner instead.
Extracting a package to PyPI
To publish a bundled package independently:
- Remove its entry from
[tool.bundle-package] - Add it as a normal dependency in
[project.dependencies](or in the appropriate optional group) - Run
make vendorto regenerate the dependency groups
The wheel gets thinner, the dependency metadata stays correct, and pip install nemo-platform[services] continues to work.
Other vendoring (make vendor)
The make vendor command also handles SDK client extensions (nemo_platform_ext, data_designer_sdk, models, filesets, safe_synthesizer_sdk, nemo_evaluator_sdk). These are not bundled via [tool.bundle-package] — they use the older [tool.vendor-package] mechanism which copies source files into the SDK tree with import rewriting. This is separate from the bundling described above and is only relevant to SDK client-side extensions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nemo_platform-0.1.1-py3-none-any.whl.
File metadata
- Download URL: nemo_platform-0.1.1-py3-none-any.whl
- Upload date:
- Size: 7.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59028dfbea662e334685f685777cbef1f1a725a70bd76ec2a23730cd8c79cd6e
|
|
| MD5 |
2a5218512f91aa1ff5ae85a6107c2404
|
|
| BLAKE2b-256 |
6754ce4975e159f9bcf14df30ce4c2ba15b2783bea52ffb6ce5b3d7151e9c5ed
|