Run Poetry commands with Artifactory integration and optional build-info collection.

This topic covers the following tasks:

When to Use

Use jf poetry if your Python project uses Poetry (with pyproject.toml) for dependency management. For pip-based projects, use jf pip. For Pipenv-based projects, use jf pipenv.

Prerequisites

  • Poetry must be installed.
  • Run jf poetry-config in the project directory before the first install (Wrapped Mode only).
  • Configure a server with jf config add or jf c add.
  • Authentication to Artifactory is required.
  • For Native Mode, configure Poetry via Artifactory's Set Me Up instructions instead.

Configuration: jf poetry-config

Generate Poetry build configuration for dependency resolution. Run this once per project before your first install.

To configure Poetry for Artifactory:

Synopsis

jf poetry-config [options]

Aliases: poc

Configuration Options

FlagDefaultDescription
--globalfalseSet to true for global configuration (all projects). Specific projects can override.
--repo-resolveRepository for dependencies resolution
--server-id-resolveArtifactory server ID for resolution. Configure with jf config add.

Configuration Examples

View Help

jf poetry-config --help

Non-Interactive Configuration with Flags

jf poetry-config --server-id-resolve=<server-id> --repo-resolve=<repo-name>

Where:

  • <server-id>: The server ID configured using jf config add
  • <repo-name>: The name of the PyPI repository in Artifactory

For example:

jf poetry-config --server-id-resolve=my-server --repo-resolve=pypi-virtual

Why Run Config First?

You must run jf poetry-config before jf poetry install (Wrapped Mode only). The config creates .jfrog/projects/poetry.yaml for dependency resolution through Artifactory. Without it, jf poetry does not know where to fetch packages.

Shortcut: In CI/CD, pass all flags non-interactively so the config step is fully automated and reproducible.

Configuration Notes

  • Config sets resolution only: jf poetry-config configures dependency resolution but not a deployer repository. To publish, pass --repo directly on jf poetry publish (Wrapped Mode) or use native poetry publish (Native Mode).
  • Run once per project: Re-run when changing the resolution repository.

Expected Output

$ jf poetry-config --server-id-resolve=my-server --repo-resolve=pypi-virtual
Poetry build configuration saved successfully.

How to Verify

After running, confirm the configuration exists:

cat .jfrog/projects/poetry.yaml

Build: jf poetry

Run Poetry commands with Artifactory integration and optional build-info collection.

To run Poetry with Artifactory integration:

Synopsis

jf poetry <poetry-arguments> [options]

Aliases: none

Arguments

ArgumentRequiredDescription
<poetry-arguments>YesArguments and options for the poetry command (for example, install, add)

Build Options

FlagDefaultDescription
--build-nameBuild name for build-info. Requires --build-number.
--build-numberBuild number for build-info. Requires --build-name.
--moduleOptional module name for build-info. Requires --build-name and --build-number.
--projectJFrog Artifactory project key

Build Examples

Help

jf poetry --help

Install with Build-Info

jf poetry install --build-name=my-app --build-number=1

Add Dependencies

jf poetry add <package-name>

Poetry Execution Modes

JFrog CLI supports two execution modes for Poetry.

Wrapped Mode (Default)

  • Uses jf poetry-config settings
  • Injects tool.poetry.source entries into pyproject.toml
  • May call poetry update during dependency resolution
  • May modify poetry.lock
  • Automatically collects build-info when provided --build-name / --build-number

Native Mode

Enable using:

export JFROG_RUN_NATIVE=true

In Native Mode, JFrog CLI:

  • Delegates to the native Poetry client without injecting configuration
  • Does not inject tool.poetry.source into pyproject.toml
  • Does not call poetry update
  • Does not modify poetry.lock
  • Does not apply jf poetry-config values or JFrog CLI YAML (.jfrog/projects/*.yaml) configuration
  • Relies entirely on Poetry's own configuration (as set via Artifactory Set Me Up)
  • Still collects build-info when --build-name and --build-number are provided via jf poetry
  • Ensures deterministic, reproducible builds

Install: Wrapped vs Native

Wrapped Mode Install

jf poetry install --build-name=my-python-app --build-number=1.2.0

Wrapped Mode behaviour:

  • May implicitly run poetry update
  • May modify poetry.lock
  • May inject repository sources into pyproject.toml

Use Native Mode if you require full lockfile fidelity.

Native Mode Install

export JFROG_RUN_NATIVE=true

# With build-info collection
jf poetry install --build-name=my-python-app --build-number=1.2.0

# Or directly (no build-info)
poetry install

Note: In Native Mode, you can use either jf poetry install (which delegates to native Poetry and collects build-info when --build-name/--build-number are provided) or poetry install directly (no build-info). Poetry must be configured via Artifactory's Set Me Up instructions to authenticate and resolve from Artifactory.

Publish: Wrapped vs Native

Wrapped Mode Publish

jf poetry publish --repo pypi-local --build-name=my-python-app --build-number=1.2.0

Behaviour:

  • May inject tool.poetry.source into pyproject.toml
  • May update dependency metadata

Use Native Mode to prevent any modifications.

Native Mode Publish

export JFROG_RUN_NATIVE=true

# With build-info collection
jf poetry publish --build-name=my-python-app --build-number=1.2.0

# Or directly (no build-info)
poetry build
poetry publish -r <REPO_ALIAS>

Credentials must be configured via Set Me Up.

Environment Variable

VariablePurposeDefault
JFROG_RUN_NATIVEEnables Native Mode and bypasses Wrapped Mode entirelyfalse

FAQ

Q: Does jf poetry-config affect Native Mode?

A: No — Native Mode ignores jf poetry-config and YAML.

Q: Can Native Mode collect build-info?

A: Yes — when you use jf poetry with --build-name and --build-number, build-info is collected even in Native Mode. If you run poetry directly (without the jf prefix), no build-info is collected.

For a cross-tool comparison of Native Mode across Maven, Gradle, npm, and Poetry, see the dedicated Native Mode page.

Universal Package Note

JFrog CLI is a pass-through to Poetry for execution and output. Output format/behaviour belongs to Poetry; if Poetry changes its output in a newer version, JFrog CLI would simply honour that without any custom adjustment.

Note: The jf poetry-config configuration is used only in Wrapped Mode. Native Mode ignores this entirely.


Important Notes

  • Config required first: Run jf poetry-config in the project directory before your first install (Wrapped Mode only).
  • Resolution only: Poetry config currently supports dependency resolution. For publishing, use jf poetry publish (Wrapped Mode) or Poetry's native poetry publish (Native Mode).
  • Poetry commands: All standard Poetry arguments work (install, add, update, lock, and others).
  • Build-info: Use --build-name and --build-number, then publish with jf rt build-publish.

CI/CD Example (GitHub Actions)

# .github/workflows/build.yml
steps:
  - uses: actions/checkout@v4
  - name: Setup JFrog CLI
    uses: jfrog/setup-jfrog-cli@v4
    env:
      JF_URL: ${{ vars.JF_URL }}
      JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
  - name: Setup Python
    uses: actions/setup-python@v5
    with:
      python-version: '3.12'
  - name: Install Poetry
    run: pip install poetry
  - name: Configure Poetry
    run: jf poetry-config --server-id-resolve=setup-jfrog-cli-server --repo-resolve=pypi-virtual
  - name: Install dependencies
    run: jf poetry install --build-name=my-python-app --build-number=${{ github.run_number }}
  - name: Publish package
    run: jf poetry publish --repo pypi-local --build-name=my-python-app --build-number=${{ github.run_number }}
  - name: Publish build info
    run: jf rt build-publish my-python-app ${{ github.run_number }}

Troubleshooting

SymptomCauseFix
no config file was foundjf poetry-config was not run (Wrapped Mode)Run jf poetry-config in the project directory
404 on jf poetry installResolution repository does not exist or name is wrongVerify the repo name matches an existing PyPI virtual repository in Artifactory
401 / 403 errorsInvalid credentials or insufficient permissionsRe-run jf config add with a valid access token
poetry.lock modified unexpectedlyWrapped Mode may run poetry update implicitlySwitch to Native Mode (export JFROG_RUN_NATIVE=true) for lockfile fidelity
jf poetry publish fails with "repo not configured"Config does not include a deploy repoPass --repo <local-repo-name> directly on the publish command
Native Mode not resolving from ArtifactoryPoetry sources not configuredConfigure Poetry via Artifactory's Set Me Up instructions

Enable debug logging: export JFROG_CLI_LOG_LEVEL=DEBUG


Related Topics