Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.2.1 instead.
Reason given by maintainers: Issue not fully fixed: may crash on split `[tool.poetry]` tables and silently omit Poetry-only dependencies. Await a fixed release.

Poetry Plugin: Migrate

License PyPI version PyPI - Python Version Poetry version Github Actions Build Code Coverage

This package is a plugin that helps you migrate pyproject.toml of your Poetry v1 project to the v2 recommended format, which follows the specification on the PyPA specs page (originally defined by PEP-621).

Check the blog post by Poetry team for more details: Announcing Poetry 2.0.0 # Supporting the project section in pyproject.toml (PEP 621).

Installation

The easiest way to add the migrate plugin is via the self add command of Poetry.

poetry self add poetry-plugin-migrate

If you used pipx to install Poetry you can add the plugin via the pipx inject command.

pipx inject poetry poetry-plugin-migrate

Otherwise, if you used pip to install Poetry you can add the plugin packages via the pip install command.

pip install poetry-plugin-migrate

Usage

The plugin provides a migrate command to migrate the current pyproject.toml to the new format.

Start with a dry run and inspect the output before writing the file:

poetry migrate --dry-run

Then run the migration, validate the result, and review the diff:

poetry migrate
poetry check --strict
poetry lock
git diff -- pyproject.toml poetry.lock

By default, the command performs a poetry check before migration and then attempts to migrate the current pyproject.toml based on several rules and the user's responses to interactive prompts. A backup file, pyproject.bak.toml, will be created before migration.

For better readability, TOML literal strings are used for string fields. If you prefer to use basic strings instead, you can use the --no-literal option.

Note: Internally, this plugin uses tomlkit, a style-preserving TOML library, to parse and modify the pyproject.toml file. Hence, the migrated result might NOT be pretty-formatted and might need reformatting.

Available Options

  • -n / --no-interaction: Skip interactive prompts and use default migration strategies. This is a global Poetry option.
  • --no-check: Skip poetry check for pyproject.toml.
  • --check-strict: Fail if check reports warnings.
  • --no-backup: Do not create a backup of pyproject.toml before migration.
  • --dry-run: Run the migration without modifying the pyproject.toml. Migration result will be printed to the console.
  • --no-literal: Use basic strings instead of literal strings in pyproject.toml.

Migration Rules

Directly-Migrated Fields

Following fields will be directly migrated:

Before After Notes
[tool.poetry.name] [project.name] -
[tool.poetry.description] [project.description] -
[tool.poetry.license] [project.license] -
[tool.poetry.keywords] [project.keywords] -
[tool.poetry.urls] [project.urls] Will be merged with other fields migrated into [project.urls]
[tool.poetry.homepage] [project.urls.homepage] -
[tool.poetry.repository] [project.urls.repository] -
[tool.poetry.documentation] [project.urls.documentation] -
[tool.poetry.plugins] [project.entry-points] -
[tool.poetry.scripts] [project.scripts] Only for those are NOT of type file
See python-poetry/poetry#9510 for details
[tool.poetry.authors] [project.authors] Format changed from "name <email>" to {"name": name, "email": email}
[tool.poetry.maintainers] [project.maintainers] Format changed from "name <email>" to {"name": name, "email": email}
[tool.poetry.extras] [project.optional-dependencies] See Dependencies Migration for details

Conditional-Migrated Fields

Fields below either need the user to choose migration strategies for them, or are migrated only under specific conditions.

The option marked with (*) is the default choice.

[tool.poetry.version]

You can choose one of the following strategies for this field:

  • (*) move it to [project]
  • or, keep it in [tool.poetry]

If you want to set the version dynamically via poetry build --local-version or you are using a plugin which sets the version dynamically, you should use dynamic versioning that keeps it in [tool.poetry] and adds "version" to [project.dynamic].

Otherwise, this field will be moved to [project].

[tool.poetry.readme]

The migration strategy for this field depends on its value:

  • If the value is a single string (one file), it will be moved to project.readme.
  • Otherwise (multiple files), it will be kept in [tool.poetry] and "readme" will be added to [project.dynamic].

[tool.poetry.classifiers]

You can choose one of the following strategies for this field:

  • (*) keep it in [tool.poetry]
  • or, move it to [project]

Per default Poetry determines classifiers for supported Python versions and license automatically.

If you define classifiers in [project], you disable the automatic enrichment. In other words, you have to define all classifiers manually.

If you want to use Poetry's automatic enrichment of classifiers, they should be kept in [tool.poetry] and 'classifiers' should be added to [project.dynamic].

[tool.poetry.dependencies.python]

You can choose one of the following strategies for this field:

  • Move to [project.requires-python]
  • Add requires-python to [project.dynamic]
  • (*) Copy value to [project.requires-python]
  • No migration and keep it as-is

See Poetry documentation for further information about this field.

[tool.poetry.dependencies]

For dependencies, you can choose one of the following strategies:

  • keep it in [tool.poetry]
  • (*) or, move it to [project]

See Dependencies Migration for details on how dependencies are migrated if you choose to move them to [project].

[tool.poetry.requires-poetry]

You can explicitly specify the required Poetry version in [tool.poetry.requires-poetry] since Poetry v2. Following constraints are available for you to choose:

  • >=2.2.1
  • >=2.2.1,<3.0.0
  • (*) No update

[build-system.requires]

You can also choose one of the following constraints of poetry-core for building:

  • >=2.0
  • >=2.0,<3.0
  • >=2.0.0
  • >=2.0.0,<3.0.0
  • (*) No update

Dependencies Migration

Entries in [tool.poetry.dependencies] and [tool.poetry.extras] will be migrated to PEP-508 strings in [project.dependencies] and [project.optional-dependencies] respectively.

Multiple constraints dependencies will be expanded into separate entries with temporary names before migration, which will then be merged into a single entry after all entries are migrated.

Fields that can be presented in a PEP-508 string (version, git, branch, tag, rev, file, path, url, subdirectory,) will be removed from the original entry.

Marker fields (python, platform, markers, extras) will only be removed if the constraint is NOT an expanded one from a multiple constraints dependency.

Then, original entries with no fields left will be removed. Others (e.g. {source = "private"}) will be kept for locking.

You can choose whether to remove brackets around version specifiers in the generated PEP-508 strings:

  • (*) remove them for PEP-508 compliance (e.g. package>=1.0,<2.0)
  • or, keep them for compatibility with old generated output (e.g. package (>=1.0,<2.0))

Per PEP-508, brackets around version specifiers should not be generated, only accepted for compatibility with PEP-345.

Dependency Groups Migration

Poetry 2.2 added support for standard PEP-735 dependency groups. Poetry 2.2.1 fixed support for declaring such a group as optional, so this plugin requires at least 2.2.1. The plugin migrates representable dependencies from [tool.poetry.group.<name>.dependencies] and the legacy [tool.poetry.dev-dependencies] table into [dependency-groups].

Poetry-specific group metadata remains in place. For example, an optional group is represented as:

[dependency-groups]
docs = ["mkdocs>=1.6,<2.0"]

[tool.poetry.group.docs]
optional = true

include-groups entries become PEP-735 { include-group = "..." } entries. If a group contains a dependency that cannot be represented safely—such as a relative path or a private source—the entire group is kept in its original Poetry table and a warning is emitted.

Example

This is an example for testing:

Before

# This file is part of the poetry-plugin-migrate project.

# Some comments on this line
[tool.poetry]
package-mode = false # Hey this should not be touched
name = "poetry-18"
version = "1.2.3"
description = "Test project that contains a pyproject.toml with Poetry v1.8 metadata."
license = "MIT"
authors = [
    "MaxMixAlex <MaxMixAlex@protonmail.com>",
    "Test Guy <test.guy@example.com>",
]
maintainers = [
    "Maintainer One <maintainer.one@example.com>",
    "Maintainer Two <maintainer.two@other.example.com>",
]
readme = ["README1.md", "README2.md"]
homepage = "https://example.com/"
repository = "https://github.com/zyf722/poetry-plugin-migrate"
documentation = "https://anyway.we.need.a.documentation.website/"
keywords = ["we", "just", "need", "some", "keywords", "for", "this", "project"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Environment :: Console",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Topic :: Software Development",
    "Topic :: System",
    "Topic :: Terminals",
    "Typing :: Typed",
    "Operating System :: OS Independent",
]
packages = [{ include = "poetry18" }] # This should not be touched too

[tool.poetry.urls]
"Test custom URL" = "https://how.are.you/doing/"
"Just another one" = "https://another.one/"

[tool.poetry.scripts]
run_as_fast_as_possible = "poetry18.__main__:main"
poet = { reference = "write_some_poem.exe", type = "file" } # File-based scripts!

[tool.poetry.extras]
birthday-present = ["chocolate"]
networking = ["requests", "httpx"]

[tool.poetry.plugins."poetry.application.plugin"]
hi = "poetry18.plugins:ActuallyThereIsNoSuchPlugin"

[[tool.poetry.source]]
name = "private"
url = "http://a.source.too.secret/simple"
priority = "supplemental"

[tool.poetry.dependencies]
python = "^3.9"
careter = "^1.2.3"
tilder = "~1.2.3"
wildcarder = "1.*"
inequalitier = ">=1.2.3,<2.0.0"
exacter = "1.2.3"
equal-exacter = "==1.2.3"
git-branch = { git = "https://github.com/example/branch.git", branch = "next" }
git-rev = { git = "https://github.com/example/rev.git", rev = "deadbeef" }
git-tag = { git = "https://github.com/example/tag.git", tag = "1.2.3" }
git-subdir = { git = "https://github.com/example/subdir.git", subdirectory = "subdir" }
local-package = { path = "../local_package/", develop = true }
local-package-absolute = { path = "/path/to/absolute/package/", develop = true }
url = { url = "https://example.com/url-package-0.1.0.tar.gz" }
baby = { version = "^0.12.0", extras = ["toy-1", "toy-2"] }
spy = { version = "*", source = "private" }
tomli = { version = "^2.0.1", python = "<3.11" }
pathlib2 = { version = "^2.2", markers = "python_version <= '3.4' or sys_platform == 'win32'" }
foo = [
    { platform = "win32", version = "^2.0", python = ">=3.8", source = "private" },
    { platform = "darwin", url = "https://example.com/example-1.0-py3-none-any.whl" },
    { platform = "linux", version = "^1.0", python = ">=3.6,<3.8" },
]
chocolate = [
    { platform = "win32", version = "^1.0", optional = true, source = "private" },
    { platform = "darwin", version = "~2.0", optional = true },
    { platform = "linux", version = "==3.0", optional = true },
]
requests = { version = "^2.0", optional = true, python = "^3.6" }
httpx = { version = "^0.23", optional = true, python = "^3.6" }

[tool.poetry.dependencies.big-guy]
version = ">=18.0.0"
allow-prereleases = true
python = "^3.9"
markers = "platform_python_implementation == 'CPython'"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

After (follows default migration strategies)

# This file is part of the poetry-plugin-migrate project.

# Some comments on this line
[tool.poetry]
package-mode = false # Hey this should not be touched
readme = ["README1.md", "README2.md"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Environment :: Console",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Topic :: Software Development",
    "Topic :: System",
    "Topic :: Terminals",
    "Typing :: Typed",
    "Operating System :: OS Independent",
]
packages = [{ include = "poetry18" }] # This should not be touched too

[tool.poetry.scripts]
poet = { reference = "write_some_poem.exe", type = "file" } # File-based scripts!

[[tool.poetry.source]]
name = "private"
url = "http://a.source.too.secret/simple"
priority = "supplemental"

[tool.poetry.dependencies]
python = "^3.9"
local-package = { path = "../local_package/", develop = true }
local-package-absolute = {  develop = true }
spy = {  source = "private" }
foo = [{ platform = "win32",  python = ">=3.8", source = "private" }, { platform = "darwin"  }, { platform = "linux",  python = ">=3.6,<3.8" }]
chocolate = [{ platform = "win32",   source = "private" }, { platform = "darwin"   }, { platform = "linux"   }]

[tool.poetry.dependencies.big-guy]
allow-prereleases = true

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[project]
name = "poetry-18"
description = "Test project that contains a pyproject.toml with Poetry v1.8 metadata."
license = "MIT"
keywords = ["we", "just", "need", "some", "keywords", "for", "this", "project"]
version = "1.2.3"
dynamic = [
    "classifiers",
    "readme",
]
authors = [
    {name = "MaxMixAlex", email = "MaxMixAlex@protonmail.com"},
    {name = "Test Guy", email = "test.guy@example.com"},
]
maintainers = [
    {name = "Maintainer One", email = "maintainer.one@example.com"},
    {name = "Maintainer Two", email = "maintainer.two@other.example.com"},
]
requires-python = '>=3.9,<4.0'
dependencies = [
    'careter>=1.2.3,<2.0.0',
    'tilder>=1.2.3,<1.3.0',
    'wildcarder==1.*',
    'inequalitier>=1.2.3,<2.0.0',
    'exacter==1.2.3',
    'equal-exacter==1.2.3',
    'git-branch @ git+https://github.com/example/branch.git@next',
    'git-rev @ git+https://github.com/example/rev.git@deadbeef',
    'git-tag @ git+https://github.com/example/tag.git@1.2.3',
    'git-subdir @ git+https://github.com/example/subdir.git#subdirectory=subdir',
    'local-package-absolute @ file:///<% LOCAL_ABSOLUTE_PACKAGE %>',
    'url @ https://example.com/url-package-0.1.0.tar.gz',
    'baby[toy-1,toy-2]>=0.12.0,<0.13.0',
    'spy',
    'tomli>=2.0.1,<3.0.0 ; python_version < "3.11"',
    'pathlib2>=2.2,<3.0 ; python_version <= "3.4" or sys_platform == "win32"',
    'big-guy>=18.0.0 ; python_version >= "3.9" and python_version < "4.0" and platform_python_implementation == "CPython"',
    'foo>=2.0,<3.0 ; python_version >= "3.8" and sys_platform == "win32"',
    'foo @ https://example.com/example-1.0-py3-none-any.whl ; sys_platform == "darwin"',
    'foo>=1.0,<2.0 ; python_version >= "3.6" and python_version < "3.8" and sys_platform == "linux"',
]

[project.urls]
homepage = "https://example.com/"
repository = "https://github.com/zyf722/poetry-plugin-migrate"
documentation = "https://anyway.we.need.a.documentation.website/"
"Test custom URL" = "https://how.are.you/doing/"
"Just another one" = "https://another.one/"

[project.entry-points."poetry.application.plugin"]
hi = "poetry18.plugins:ActuallyThereIsNoSuchPlugin"


[project.scripts]
run_as_fast_as_possible = "poetry18.__main__:main"

[project.optional-dependencies]
birthday-present = [
    'chocolate==3.0 ; sys_platform == "linux"',
    'chocolate>=2.0,<2.1 ; sys_platform == "darwin"',
    'chocolate>=1.0,<2.0 ; sys_platform == "win32"',
]
networking = [
    'requests>=2.0,<3.0 ; python_version >= "3.6" and python_version < "4.0"',
    'httpx>=0.23,<0.24 ; python_version >= "3.6" and python_version < "4.0"',
]

Contributing

This plugin still requires more testing and feedback to improve its quality and may contain bugs. Contributions in the form of raising issues and code contributions are highly welcome.

It is strongly recommended to follow the Conventional Commits specification when writing commit messages and creating pull requests.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

poetry_plugin_migrate-0.2.0.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

poetry_plugin_migrate-0.2.0-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file poetry_plugin_migrate-0.2.0.tar.gz.

File metadata

  • Download URL: poetry_plugin_migrate-0.2.0.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for poetry_plugin_migrate-0.2.0.tar.gz
Algorithm Hash digest
SHA256 30b755f16809982c3231745c5b955a6b54b613eed6ce57c514a5c7e86da5712c
MD5 941bc74f2f686750cff90954be568310
BLAKE2b-256 28870dfa6a5c1c2d8da3f970f04c0d86e17405acdf309fd4da83bf97a5c708b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for poetry_plugin_migrate-0.2.0.tar.gz:

Publisher: release.yml on zyf722/poetry-plugin-migrate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file poetry_plugin_migrate-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for poetry_plugin_migrate-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 727bff0d04d029d26c98750295dcd862b1484a253b5f6d3780d8499a28500dff
MD5 630846069abc48019f04e7bb6afe0751
BLAKE2b-256 5b1771d890c8946a95d9a7f1e3bb16c2c776482ba85f8fa8403da1a357632efe

See more details on using hashes here.

Provenance

The following attestation bundles were made for poetry_plugin_migrate-0.2.0-py3-none-any.whl:

Publisher: release.yml on zyf722/poetry-plugin-migrate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page