publish

package
v0.0.0-...-cc320b4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: BSD-3-Clause Imports: 34 Imported by: 0

README

Publishing Encrypted Private Python Ingredients

This guide walks through publishing a private Python package to the ActiveState Platform with state publish --build, declaring its dependencies, and changing those dependencies later.

With --build, the State Tool packs your source directory into a wheel and encrypts it with your organization's key before uploading it. The platform only sees the ingredient's name, namespace, version and dependencies, not your source code. Projects in your organization decrypt and install it into their Python runtime's site-packages.

Before You Start

  • You are logged in: state auth.
  • You are in a checkout of a project owned by your organization (it has an activestate.yaml). The project determines which organization's key encrypts the package.
  • Your organization's key service is configured (state config set privateingredient.key_service_url <url>, plus the privateingredient.* credential settings your administrator gives you). Without it nothing is uploaded.

Throughout this guide, <org> is your organization name and mypkg is the package being published.

1. Lay Out the Source

Point --build at a directory whose children are the importable packages. A pyproject.toml beside them is optional, but it lets the State Tool read the name, version, description and dependencies, so you don't have to pass them as flags.

mypkg-src/
├── pyproject.toml
└── mypkg/
    ├── __init__.py
    └── core.py

Only pure-Python packages are supported: compiled files (.so, .pyd, .dll, .dylib) are rejected. __pycache__ directories, *.pyc files and version-control directories are left out of the wheel.

2. Declare Dependencies

List them in pyproject.toml the same way you would for pip:

[project]
name = "mypkg"
version = "1.0.0"
description = "Internal helpers for the data team"
dependencies = [
  "requests>=2.31,<3",
  "six~=1.16",
  'pywin32>=300; sys_platform == "win32"',
  'tomli>=1; python_version < "3.11"',
]

Each entry becomes a runtime dependency on the platform's Python package of that name. Version ranges carry over, with ~=1.16 becoming >=1.16,<2 and ==4.2.* becoming >=4.2,<4.3. An entry without a range, such as "click", accepts any version (>=0).

Platform and Python version markers become conditions, so the dependency is only installed where it applies:

Marker Installed only on
sys_platform == "win32", platform_system == "Windows", os_name == "nt" Windows
sys_platform == "linux", platform_system == "Linux" Linux
sys_platform == "darwin", platform_system == "Darwin" macOS
python_version < "3.11" (also <=, >, >=, ==) matching Python versions
python_full_version >= "3.9.2" matching Python versions

Several of these can be combined with and, e.g. sys_platform == "win32" and python_version >= "3.10".

Anything else is skipped with a notice when you publish: markers using or, parentheses or !=, other markers such as platform_machine, optional dependencies (extra == "..."), and direct URL references (pkg @ https://...). Add a skipped dependency by hand with --depend or a meta file (see step 5) if it is required.

3. Publish

From the project checkout:

state publish --build ./mypkg-src --namespace private/<org>/python

The namespace must be under private/<org>, the organization that owns the project. Without --namespace, it is private/<org>/python when the source directory has a pyproject.toml, and private/<org> otherwise. Before uploading, the State Tool shows the ingredient it is about to publish and asks for confirmation:

Skipping pyproject.toml dependency 'colorama; platform_machine == "x86_64"' (unsupported environment marker
'platform_machine == "x86_64"'). Add it with '--depend' if it is required.

Prepared the following ingredient:

name: mypkg
namespace: private/<org>/python
version: 1.0.0
description: Internal helpers for the data team
dependencies:
    - dependency:
        name: requests
        namespace: language/python
        versionRequirements: '>=2.31,<3'
        type: runtime
    - dependency:
        name: pywin32
        namespace: language/python
        versionRequirements: '>=300'
        type: runtime
      conditions:
        - name: Windows
          namespace: kernel
          versionRequirements: '>=0'
    ...
    - dependency:
        name: private-builder
        namespace: builder
        versionRequirements: '>=0'

The name and version are built into the package, so they can't be changed. To change them, publish again with
'--name' or '--version'.

Do you want to publish this ingredient? Answer 'n' to edit it or save it to a file instead. (Y/n)

Check the dependency list here: it is exactly what will be published. The private-builder dependency is always added; it is what decrypts and installs the package, so leave it in place.

If something is wrong, answer n and choose one of:

  • Edit it in my editor: opens the meta data in $EDITOR (or the default program for .yaml files), then shows the result for confirmation again. You can change the namespace here: it is checked the same way as --namespace, and if it can't be used (it is outside your organization, or the version already exists there), the previous one is kept and the reason is shown. The name and version can't be changed this way, because the package was already built with them: if you change them, your edits are saved to a meta file as below.
  • Save it to a meta file to edit and publish later: writes mypkg-1.0.0.meta.yaml to the current directory and prints the command to publish it, e.g. state publish --build ./mypkg-src --meta mypkg-1.0.0.meta.yaml. Edit the file, then run that command. The meta file takes precedence over pyproject.toml, so its name, version and dependency list are used instead.
  • Cancel: nothing is published.

Flags override pyproject.toml: --name, --version and --description replace the values in it, and any --depend, --depend-runtime, --depend-build or --depend-test flag replaces its whole dependency list.

4. Install and Check

In any project of the same organization:

state install private/<org>/python:mypkg --ts now
state exec python3 -- -c "import mypkg"

--ts now makes the solver pick up the version you just published. The install summary lists the dependencies that were pulled in, and conditional dependencies only appear on matching platforms.

The machine installing the package needs the same key service settings as the one that published it, because the package is decrypted during installation.

5. Change the Dependencies of a Published Version

To change the dependencies of a version that is already published, export its meta file, edit it, and publish it back as a new revision with --edit.

Export the current meta file:

state export ingredient-meta private/<org>/python/mypkg@1.0.0 > meta.yaml

Leave out @1.0.0 to export the latest version. The file holds the ingredient's name, namespace, version and its complete dependency list:

name: mypkg
namespace: private/<org>/python
version: 1.0.0
description: Internal helpers for the data team
dependencies:
    - dependency:
        name: private-builder
        namespace: builder
        versionRequirements: '>=0'
        type: build
      conditions: []
    - dependency:
        name: requests
        namespace: language/python
        versionRequirements: '>=2.31,<3'
        type: runtime
      conditions: []
    ...

The meta file has these fields:

Field Meaning
name The name of the ingredient.
namespace Where the ingredient is published, under private/<org>, e.g. private/<org>/python.
version The version, following semantic versioning. It must match the version in the source file name, if any.
description A short description of the ingredient. It can't be changed on an existing version.
authors Optional. The people who contributed to it, each with name, email and websites. They can't be changed on an existing version.
dependencies Optional. The ingredients it requires, described below.
features Optional. The features it provides, each with name, namespace and version.

Edit the dependencies list. Change version ranges, remove entries, or add new ones. Each entry nests its fields under dependency:, with optional conditions: beside it:

    - dependency:
        name: urllib3
        namespace: language/python
        versionRequirements: '>=2'
        type: runtime
      conditions:
        - name: Linux
          namespace: kernel
          versionRequirements: '>=0'

For conditions, the kernel names are Windows, Linux and Darwin (namespace kernel). A Python version condition is name: python, namespace: language, with a requirement such as <3.11.

Publish the revision:

state publish --edit --build ./mypkg-src --meta meta.yaml

The platform requires the source with every revision, so pass --build even when only the meta data changes.

Things to know about --edit:

  • The meta file replaces the whole dependency list. Anything you delete from it is removed from the ingredient. Dependencies in pyproject.toml are not used when the meta file lists its own. If neither the meta file nor pyproject.toml lists any, the previous revision's dependencies are kept.
  • Name, namespace and version identify what you are editing; they cannot be changed. To publish under a new version, see step 6.
  • Authors and description cannot be changed on an existing version. The exported file leaves authors out, and adding any is refused with "Authors cannot be changed when editing an existing version." It includes the current description. If you change it, the change is ignored: the confirmation shows the current description and says so, and you can still publish the rest of your edits.
  • The language/python dependencies the platform adds by itself come back automatically, so it does no harm if they are missing from your file.

Run the export again afterwards to confirm the change.

6. Publish a New Version

Bump the version in pyproject.toml (or pass --version) and publish as in step 3, without --edit. A new version takes its dependencies from pyproject.toml, flags and --meta as usual and does not inherit them from the previous version.

Publishing a version that already exists without --edit is refused, so an existing version can't be overwritten by accident.

Troubleshooting

Message What to do
Could not determine the ingredient name and version The message lists each missing field and why. Add it to pyproject.toml's [project] table, pass --name/--version, or set it in a --meta file. A version listed in [project].dynamic can't be read and must be given this way.
The '--build' flag requires a namespace under 'private/<org>' Use a namespace under the organization that owns the project you are in.
org key does not belong to this project's organization The key service returned another organization's key. Check that you are in the right project.
No organization key service is configured Configure the privateingredient.* settings (see Before You Start).
Ingredient ... already exists. To edit an existing ingredient ... Pass --edit to change an existing version, or bump the version to publish a new one.
Skipping pyproject.toml dependency ... The marker is not supported. Add the dependency with --depend or in a meta file.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FetchMeta

func FetchMeta(namespace, name, version string, auth *authentication.Auth) (*request.PublishVariables, error)

FetchMeta returns the meta file contents of an existing ingredient version (the latest one when version is empty), in the format the --meta flag accepts. Its dependencies are the complete set, so the file can be modified and passed back with --edit to replace them. Authors are left out because the platform rejects them on a revision of an existing version; the description is included, and --edit accepts it as long as it is unchanged.

Types

type Params

type Params struct {
	Name           string
	Version        string
	Namespace      string
	Owner          string
	Description    string
	Authors        captain.UsersValue
	Depends        captain.PackagesValue
	DependsRuntime captain.PackagesValue
	DependsBuild   captain.PackagesValue
	DependsTest    captain.PackagesValue
	Features       captain.PackagesValue
	Filepath       string
	MetaFilepath   string
	Build          string
	Edit           bool
	Editor         bool
}

type ParentIngredient

type ParentIngredient struct {
	IngredientID        strfmt.UUID
	IngredientVersionID strfmt.UUID
	Version             string
	Dependencies        []inventory_models.Dependency `json:"dependencies"`
}

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

func New

func New(prime primeable) *Runner

func (*Runner) OpenInEditor

func (r *Runner) OpenInEditor(pr *request.PublishVariables) error

func (*Runner) Run

func (r *Runner) Run(params *Params) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL