Poetry 构建的包缺少运行时依赖项
Package built by Poetry is missing runtime dependencies
我一直在从事一个项目,到目前为止只涉及构建一些云基础设施,现在我正在尝试 add a CLI 来简化 运行 一些 AWS Lambda。不幸的是,使用 poetry build
构建的 sdist 和 wheel 包似乎都不包含依赖项,所以我必须手动 pip install
所有这些到 运行 命令。基本上我
- 运行
poetry build
项目中,
cd "$(mktemp --directory)"
,
python -m venv .venv
,
. .venv/bin/activate
,
pip install /path/to/result/of/poetry/build/above
,然后
- 运行 新的 .venv/bin/ 可执行文件。
此时可执行文件失败,因为pip
没有安装任何依赖包。 如果我 pip show PACKAGE
Requires
行是空的。
Poetry 手册似乎没有指定如何 link 依赖于构建的包,那么我必须做什么呢?
我正在使用一些可选的依赖项,这会干扰构建过程吗?需要明确的是,即使是非可选依赖项也不会出现在 package 依赖项中。
pyproject.toml:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.black]
line-length = 100
[tool.coverage.report]
exclude_lines = [
'if TYPE_CHECKING:',
'if __name__ == "__main__":',
'pragma: no cover',
]
fail_under = 100
[tool.coverage.run]
branch = true
omit = [
".venv/*",
]
[tool.isort]
case_sensitive = true
line_length = 100
profile = "black"
[tool.mypy]
show_error_codes = true
strict = true
[[tool.mypy.overrides]]
module = [
"jsonschema",
"jsonschema._utils",
"jsonschema.validators",
"multihash",
"pystac",
"pystac.layout",
"pytest_subtests",
"smart_open",
"linz_logger"
]
ignore_missing_imports = true
[tool.poetry]
name = "geostore"
version = "0.1.0"
description = "Central storage, management and access for important geospatial datasets developed by LINZ"
authors = [
"Bill M. Nelson <bmnelson@linz.govt.nz>",
"Daniel Silk <dsilk@linz.govt.nz>",
"Ivan Mincik <ivan.mincik@gmail.com>",
"Mitchell Paff <mpaff@linz.govt.nz>",
"Sandro Santilli <strk@kbt.io>",
"Simon Planzer <splanzer@linz.govt.nz>",
"Victor Engmark <vengmark@linz.govt.nz>",
]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/linz/geostore"
repository = "https://github.com/linz/geostore"
keywords = [
"SpatioTemporal Asset Catalog (STAC)",
"Toitū Te Whenua Land Information New Zealand",
]
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Console",
"Framework :: AWS CDK",
"Framework :: Pytest",
"Intended Audience :: End Users/Desktop",
"Intended Audience :: Information Technology",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: POSIX",
"Programming Language :: Python :: 3.8",
"Topic :: Communications :: File Sharing",
"Topic :: Scientific/Engineering :: GIS",
"Topic :: Utilities",
"Typing :: Typed",
]
[tool.poetry.dependencies]
python = "^3.8"
"aws-cdk.aws-dynamodb" = {version = "*", optional = true}
"aws-cdk.aws-ec2" = {version = "*", optional = true}
"aws-cdk.aws-ecr" = {version = "*", optional = true}
"aws-cdk.aws-ecr_assets" = {version = "*", optional = true}
"aws-cdk.aws-ecs" = {version = "*", optional = true}
"aws-cdk.aws-events" = {version = "*", optional = true}
"aws-cdk.aws-events-targets" = {version = "*", optional = true}
"aws-cdk.aws-iam" = {version = "*", optional = true}
"aws-cdk.aws-lambda" = {version = "*", optional = true}
"aws-cdk.aws-lambda-event-sources" = {version = "*", optional = true}
"aws-cdk.aws-lambda-python" = {version = "*", optional = true}
"aws-cdk.aws-s3" = {version = "*", optional = true}
"aws-cdk.aws-sns" = {version = "*", optional = true}
"aws-cdk.aws-stepfunctions" = {version = "*", optional = true}
"aws-cdk.aws-stepfunctions_tasks" = {version = "*", optional = true}
awscli = {version = "*", optional = true}
boto3 = "*"
cattrs = {version = "*", optional = true}
jsonschema = {version = "*", extras = ["format"], optional = true}
multihash = {version = "*", optional = true}
pynamodb = {version = "*", optional = true}
pystac = {version = "*", optional = true}
slack-sdk = {version = "*", extras = ["models", "webhook"], optional = true}
smart-open = {version = "*", extras = ["s3"], optional = true}
strict-rfc3339 = {optional = true, version = "*"}
typer = "*"
ulid-py = {version = "*", optional = true}
linz-logger = {version = "*", optional = true}
[tool.poetry.dev-dependencies]
black = "*"
boto3-stubs = {version = "*", extras = ["batch", "dynamodb", "events", "lambda", "lambda-python", "s3", "s3control", "sns", "sqs", "ssm", "stepfunctions", "sts"]}
gitlint = "*"
ipdb = "*"
isort = "*"
language-formatters-pre-commit-hooks = "*"
mutmut = "*"
mypy = "*"
pre-commit = "*"
pylint = "*"
pytest = "*"
pytest-randomly = "*"
pytest-socket = "*"
pytest-subtests = "*"
pytest-timeout = "*"
types-pkg-resources = "*"
types-python-dateutil = "*"
types-requests = "*"
types-six = "*"
types-toml = "*"
[tool.poetry.dev-dependencies.coverage]
version = "*"
extras = ["toml"]
[tool.poetry.extras]
cdk = [
"aws-cdk.aws-dynamodb",
"aws-cdk.aws-ec2",
"aws-cdk.aws-ecr",
"aws-cdk.aws-ecr_assets",
"aws-cdk.aws-ecs",
"aws-cdk.aws-events",
"aws-cdk.aws-events-targets",
"aws-cdk.aws-iam",
"aws-cdk.aws-lambda",
"aws-cdk.aws-lambda-event-sources",
"aws-cdk.aws-lambda-python",
"aws-cdk.aws-s3",
"aws-cdk.aws-sns",
"aws-cdk.aws-stepfunctions",
"aws-cdk.aws-stepfunctions_tasks",
"awscli",
"cattrs",
]
check_files_checksums = [
"boto3",
"linz-logger",
"multihash",
"pynamodb",
]
check_stac_metadata = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"strict-rfc3339",
]
cli = [
"boto3",
"typer",
]
content_iterator = [
"jsonschema",
"linz-logger",
"pynamodb",
]
datasets = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"pystac",
"ulid-py",
]
dataset_versions = [
"jsonschema",
"linz-logger",
"pynamodb",
"ulid-py",
]
import_asset_file = [
"boto3",
"linz-logger",
"smart-open",
]
import_dataset = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"smart-open",
"ulid-py",
]
import_metadata_file = [
"boto3",
"linz-logger",
]
import_status = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
]
notify_status_update = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"slack-sdk"
]
populate_catalog = [
"boto3",
"jsonschema",
"linz-logger",
"pystac",
]
update_dataset_catalog = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"ulid-py"
]
upload_status = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
]
validation_summary = [
"jsonschema",
"linz-logger",
"pynamodb",
]
[tool.poetry.scripts]
geostore = "geostore.cli:app"
[tool.pylint.MASTER]
disable = [
"duplicate-code",
"missing-class-docstring",
"missing-function-docstring",
"missing-module-docstring",
]
load-plugins = [
"pylint.extensions.mccabe",
]
max-complexity = 6
[tool.pytest.ini_options]
addopts = "--randomly-dont-reset-seed"
markers = [
"infrastructure: requires a deployed infrastructure",
]
python_functions = "should_*"
testpaths = [
"tests"
]
如您所见,boto3 和 typer 运行时间依赖项不是可选的,所以我希望在 poetry show geostore
.
中看到它们
这似乎是 Poetry 中的一个错误。或者至少从文档中不清楚在您这样的情况下预期的行为是什么。
在您的 pyproject.toml
中,您根据本节的要求指定两个依赖项:
[tool.poetry.dependencies]
…
awscli = {version = "*", optional = true}
boto3 = "*"
…
typer = "*"
…
因此,与 awscli
等许多人相反,boto3
和 typer
应该是必需的,因为 optional
属性未设置且默认为 false
.但是您还在本节中将两个必需的依赖项列为“额外”:
[tool.poetry.extras]
…
cli = [
"boto3",
"typer",
]
…
诗歌认为这意味着它们实际上是可选的,而不是必需的。在某种程度上,这是有道理的,因为 extras 实际上是可选的。如果您检查由 Poetry 构建的 .whl
wheel 文件(它只是一个 zip 存档),特别是其中的 METADATA
文件(这是安装包时 Pip 所指的),那么它包含这一行:
Requires-Dist: typer; extra == "cli"
因此该依赖项实际上是可选的:只有当用户使用 pip install geostore[cli]
明确要求时才会安装它。
解决方案很简单:从 extras
部分中删除对所需依赖项的所有引用。反正那里也不需要它们。
Poetry 文档实际上并不清楚 optional
的真正含义。该属性(目前)仅在 section on the pyproject.toml
file 中简要提及。也可以争辩说,如果 optional
是 false
,那么 extras
部分不应覆盖该值。
我一直在从事一个项目,到目前为止只涉及构建一些云基础设施,现在我正在尝试 add a CLI 来简化 运行 一些 AWS Lambda。不幸的是,使用 poetry build
构建的 sdist 和 wheel 包似乎都不包含依赖项,所以我必须手动 pip install
所有这些到 运行 命令。基本上我
- 运行
poetry build
项目中, cd "$(mktemp --directory)"
,python -m venv .venv
,. .venv/bin/activate
,pip install /path/to/result/of/poetry/build/above
,然后- 运行 新的 .venv/bin/ 可执行文件。
此时可执行文件失败,因为pip
没有安装任何依赖包。 如果我 pip show PACKAGE
Requires
行是空的。
Poetry 手册似乎没有指定如何 link 依赖于构建的包,那么我必须做什么呢?
我正在使用一些可选的依赖项,这会干扰构建过程吗?需要明确的是,即使是非可选依赖项也不会出现在 package 依赖项中。
pyproject.toml:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.black]
line-length = 100
[tool.coverage.report]
exclude_lines = [
'if TYPE_CHECKING:',
'if __name__ == "__main__":',
'pragma: no cover',
]
fail_under = 100
[tool.coverage.run]
branch = true
omit = [
".venv/*",
]
[tool.isort]
case_sensitive = true
line_length = 100
profile = "black"
[tool.mypy]
show_error_codes = true
strict = true
[[tool.mypy.overrides]]
module = [
"jsonschema",
"jsonschema._utils",
"jsonschema.validators",
"multihash",
"pystac",
"pystac.layout",
"pytest_subtests",
"smart_open",
"linz_logger"
]
ignore_missing_imports = true
[tool.poetry]
name = "geostore"
version = "0.1.0"
description = "Central storage, management and access for important geospatial datasets developed by LINZ"
authors = [
"Bill M. Nelson <bmnelson@linz.govt.nz>",
"Daniel Silk <dsilk@linz.govt.nz>",
"Ivan Mincik <ivan.mincik@gmail.com>",
"Mitchell Paff <mpaff@linz.govt.nz>",
"Sandro Santilli <strk@kbt.io>",
"Simon Planzer <splanzer@linz.govt.nz>",
"Victor Engmark <vengmark@linz.govt.nz>",
]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/linz/geostore"
repository = "https://github.com/linz/geostore"
keywords = [
"SpatioTemporal Asset Catalog (STAC)",
"Toitū Te Whenua Land Information New Zealand",
]
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Console",
"Framework :: AWS CDK",
"Framework :: Pytest",
"Intended Audience :: End Users/Desktop",
"Intended Audience :: Information Technology",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: POSIX",
"Programming Language :: Python :: 3.8",
"Topic :: Communications :: File Sharing",
"Topic :: Scientific/Engineering :: GIS",
"Topic :: Utilities",
"Typing :: Typed",
]
[tool.poetry.dependencies]
python = "^3.8"
"aws-cdk.aws-dynamodb" = {version = "*", optional = true}
"aws-cdk.aws-ec2" = {version = "*", optional = true}
"aws-cdk.aws-ecr" = {version = "*", optional = true}
"aws-cdk.aws-ecr_assets" = {version = "*", optional = true}
"aws-cdk.aws-ecs" = {version = "*", optional = true}
"aws-cdk.aws-events" = {version = "*", optional = true}
"aws-cdk.aws-events-targets" = {version = "*", optional = true}
"aws-cdk.aws-iam" = {version = "*", optional = true}
"aws-cdk.aws-lambda" = {version = "*", optional = true}
"aws-cdk.aws-lambda-event-sources" = {version = "*", optional = true}
"aws-cdk.aws-lambda-python" = {version = "*", optional = true}
"aws-cdk.aws-s3" = {version = "*", optional = true}
"aws-cdk.aws-sns" = {version = "*", optional = true}
"aws-cdk.aws-stepfunctions" = {version = "*", optional = true}
"aws-cdk.aws-stepfunctions_tasks" = {version = "*", optional = true}
awscli = {version = "*", optional = true}
boto3 = "*"
cattrs = {version = "*", optional = true}
jsonschema = {version = "*", extras = ["format"], optional = true}
multihash = {version = "*", optional = true}
pynamodb = {version = "*", optional = true}
pystac = {version = "*", optional = true}
slack-sdk = {version = "*", extras = ["models", "webhook"], optional = true}
smart-open = {version = "*", extras = ["s3"], optional = true}
strict-rfc3339 = {optional = true, version = "*"}
typer = "*"
ulid-py = {version = "*", optional = true}
linz-logger = {version = "*", optional = true}
[tool.poetry.dev-dependencies]
black = "*"
boto3-stubs = {version = "*", extras = ["batch", "dynamodb", "events", "lambda", "lambda-python", "s3", "s3control", "sns", "sqs", "ssm", "stepfunctions", "sts"]}
gitlint = "*"
ipdb = "*"
isort = "*"
language-formatters-pre-commit-hooks = "*"
mutmut = "*"
mypy = "*"
pre-commit = "*"
pylint = "*"
pytest = "*"
pytest-randomly = "*"
pytest-socket = "*"
pytest-subtests = "*"
pytest-timeout = "*"
types-pkg-resources = "*"
types-python-dateutil = "*"
types-requests = "*"
types-six = "*"
types-toml = "*"
[tool.poetry.dev-dependencies.coverage]
version = "*"
extras = ["toml"]
[tool.poetry.extras]
cdk = [
"aws-cdk.aws-dynamodb",
"aws-cdk.aws-ec2",
"aws-cdk.aws-ecr",
"aws-cdk.aws-ecr_assets",
"aws-cdk.aws-ecs",
"aws-cdk.aws-events",
"aws-cdk.aws-events-targets",
"aws-cdk.aws-iam",
"aws-cdk.aws-lambda",
"aws-cdk.aws-lambda-event-sources",
"aws-cdk.aws-lambda-python",
"aws-cdk.aws-s3",
"aws-cdk.aws-sns",
"aws-cdk.aws-stepfunctions",
"aws-cdk.aws-stepfunctions_tasks",
"awscli",
"cattrs",
]
check_files_checksums = [
"boto3",
"linz-logger",
"multihash",
"pynamodb",
]
check_stac_metadata = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"strict-rfc3339",
]
cli = [
"boto3",
"typer",
]
content_iterator = [
"jsonschema",
"linz-logger",
"pynamodb",
]
datasets = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"pystac",
"ulid-py",
]
dataset_versions = [
"jsonschema",
"linz-logger",
"pynamodb",
"ulid-py",
]
import_asset_file = [
"boto3",
"linz-logger",
"smart-open",
]
import_dataset = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"smart-open",
"ulid-py",
]
import_metadata_file = [
"boto3",
"linz-logger",
]
import_status = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
]
notify_status_update = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"slack-sdk"
]
populate_catalog = [
"boto3",
"jsonschema",
"linz-logger",
"pystac",
]
update_dataset_catalog = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
"ulid-py"
]
upload_status = [
"boto3",
"jsonschema",
"linz-logger",
"pynamodb",
]
validation_summary = [
"jsonschema",
"linz-logger",
"pynamodb",
]
[tool.poetry.scripts]
geostore = "geostore.cli:app"
[tool.pylint.MASTER]
disable = [
"duplicate-code",
"missing-class-docstring",
"missing-function-docstring",
"missing-module-docstring",
]
load-plugins = [
"pylint.extensions.mccabe",
]
max-complexity = 6
[tool.pytest.ini_options]
addopts = "--randomly-dont-reset-seed"
markers = [
"infrastructure: requires a deployed infrastructure",
]
python_functions = "should_*"
testpaths = [
"tests"
]
如您所见,boto3 和 typer 运行时间依赖项不是可选的,所以我希望在 poetry show geostore
.
这似乎是 Poetry 中的一个错误。或者至少从文档中不清楚在您这样的情况下预期的行为是什么。
在您的 pyproject.toml
中,您根据本节的要求指定两个依赖项:
[tool.poetry.dependencies]
…
awscli = {version = "*", optional = true}
boto3 = "*"
…
typer = "*"
…
因此,与 awscli
等许多人相反,boto3
和 typer
应该是必需的,因为 optional
属性未设置且默认为 false
.但是您还在本节中将两个必需的依赖项列为“额外”:
[tool.poetry.extras]
…
cli = [
"boto3",
"typer",
]
…
诗歌认为这意味着它们实际上是可选的,而不是必需的。在某种程度上,这是有道理的,因为 extras 实际上是可选的。如果您检查由 Poetry 构建的 .whl
wheel 文件(它只是一个 zip 存档),特别是其中的 METADATA
文件(这是安装包时 Pip 所指的),那么它包含这一行:
Requires-Dist: typer; extra == "cli"
因此该依赖项实际上是可选的:只有当用户使用 pip install geostore[cli]
明确要求时才会安装它。
解决方案很简单:从 extras
部分中删除对所需依赖项的所有引用。反正那里也不需要它们。
Poetry 文档实际上并不清楚 optional
的真正含义。该属性(目前)仅在 section on the pyproject.toml
file 中简要提及。也可以争辩说,如果 optional
是 false
,那么 extras
部分不应覆盖该值。