Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into pre-commit-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nzig committed Sep 28, 2022
2 parents 5a94ca6 + 92dee36 commit 0aea78e
Show file tree
Hide file tree
Showing 50 changed files with 635 additions and 655 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ jobs:

- name: Ensure cache is healthy
if: steps.cache.outputs.cache-hit == 'true'
run: timeout 10s poetry run pip --version || rm -rf .venv
run: |
# `timeout` is not available on macOS, so we define a custom function.
[ "$(command -v timeout)" ] || function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
# Using `timeout` is a safeguard against the Poetry command hanging for some reason.
timeout 10s poetry run pip --version || rm -rf .venv
# XXX: https://github.com/pypa/pip/issues/11352 causes random failures -- remove once fixed in a release.
- name: Upgrade pip on 3.11 for macOS
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ repos:
- flake8-pie==0.16.0

- repo: https://github.com/asottile/pyupgrade
rev: v2.38.0
rev: v2.38.2
hooks:
- id: pyupgrade
args: [--py37-plus]
Expand Down
4 changes: 4 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@ poetry publish

It can also build the package if you pass it the `--build` option.

{{% note %}}
See [Publishable Repositories]({{< relref "repositories/#publishable-repositories" >}}) for more information on how to configure and use publishable repositories.
{{% /note %}}

### Options

* `--repository (-r)`: The repository to register the package to (default: `pypi`).
Expand Down
6 changes: 3 additions & 3 deletions docs/dependency-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,14 +302,14 @@ Sometimes, one of your dependency may have different version ranges depending
on the target Python versions.

Let's say you have a dependency on the package `foo` which is only compatible
with Python <3.0 up to version 1.9 and compatible with Python 3.4+ from version 2.0:
with Python 3.6-3.7 up to version 1.9, and compatible with Python 3.8+ from version 2.0:
you would declare it like so:

```toml
[tool.poetry.dependencies]
foo = [
{version = "<=1.9", python = "^3.6"},
{version = "^2.0", python = "^3.8"}
{version = "<=1.9", python = ">=3.6,<3.8"},
{version = "^2.0", python = ">=3.8"}
]
```

Expand Down
8 changes: 4 additions & 4 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ demo = "poetry_demo_plugin.plugin:MyPlugin"
Every plugin has to supply a class which implements the `poetry.plugins.Plugin` interface.

The `activate()` method of the plugin is called after the plugin is loaded
and receives an instance of `Poetry` as well as an instance of `cleo.io.IO`.
and receives an instance of `Poetry` as well as an instance of `cleo.io.io.IO`.

Using these two objects all configuration can be read
and all public internal objects and state can be manipulated as desired.
Expand Down Expand Up @@ -78,7 +78,7 @@ If you want to add commands or options to the `poetry` script you need
to create an application plugin which implements the `poetry.plugins.ApplicationPlugin` interface.

The `activate()` method of the application plugin is called after the plugin is loaded
and receives an instance of `console.Application`.
and receives an instance of `poetry.console.Application`.

```python
from cleo.commands.command import Command
Expand Down Expand Up @@ -119,7 +119,7 @@ This will help keep the performances of Poetry good.
{{% /note %}}

The plugin also must be declared in the `pyproject.toml` file of the plugin package
as an `application.plugin` plugin:
as a `poetry.application.plugin` plugin:

```toml
[tool.poetry.plugins."poetry.application.plugin"]
Expand All @@ -135,7 +135,7 @@ A plugin **must not** remove or modify in any way the core commands of Poetry.

Plugins can also listen to specific events and act on them if necessary.

These events are fired by [Cleo](https://github.com/sdispater/cleo)
These events are fired by [Cleo](https://github.com/python-poetry/cleo)
and are accessible from the `cleo.events.console_events` module.

- `COMMAND`: this event allows attaching listeners before any command is executed.
Expand Down
22 changes: 17 additions & 5 deletions docs/pyproject.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,27 @@ Dependencies listed in [dependency groups]({{< relref "managing-dependencies#dep

## `plugins`

Poetry supports arbitrary plugins which work similarly to
[setuptools entry points](http://setuptools.readthedocs.io/en/latest/setuptools.html).
To match the example in the setuptools documentation, you would use the following:
Poetry supports arbitrary plugins, which are exposed as the ecosystem-standard [entry points](https://packaging.python.org/en/latest/specifications/entry-points/) and discoverable using `importlib.metadata`. This is similar to (and compatible with) the entry points feature of `setuptools`.
The syntax for registering a plugin is:

```toml
[tool.poetry.plugins] # Optional super table

[tool.poetry.plugins."blogtool.parsers"]
".rst" = "some_module:SomeClass"
[tool.poetry.plugins."A"]
"B" = "C:D"
```
Which are:

- `A` - type of the plugin, for example `poetry.plugin` or `flake8.extension`
- `B` - name of the plugin
- `C` - python module import path
- `D` - the entry point of the plugin (a function or class)

Example (from [`poetry-plugin-export`](http://github.com/python-poetry/poetry-plugin-export)):

```toml
[tool.poetry.plugins."poetry.application.plugin"]
export = "poetry_plugin_export.plugins:ExportApplicationPlugin"
```

## `urls`
Expand Down
48 changes: 27 additions & 21 deletions src/poetry/packages/locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from tomlkit.items import Table
from tomlkit.toml_document import TOMLDocument

from poetry.repositories import Repository
from poetry.repositories.lockfile_repository import LockfileRepository

logger = logging.getLogger(__name__)
_GENERATED_IDENTIFIER = "@" + "generated"
Expand All @@ -47,7 +47,8 @@


class Locker:
_VERSION = "1.1"
_VERSION = "2.0"
_READ_VERSION_RANGE = ">=1,<3"

_legacy_keys = ["dependencies", "source", "extras", "dev-dependencies"]
_relevant_keys = [*_legacy_keys, "group"]
Expand Down Expand Up @@ -91,22 +92,23 @@ def is_fresh(self) -> bool:

return False

def locked_repository(self) -> Repository:
def locked_repository(self) -> LockfileRepository:
"""
Searches and returns a repository of locked packages.
"""
from poetry.factory import Factory
from poetry.repositories import Repository
from poetry.repositories.lockfile_repository import LockfileRepository

repository = LockfileRepository()

if not self.is_locked():
return Repository("poetry-locked")
return repository

lock_data = self.lock_data
packages = Repository("poetry-locked")
locked_packages = cast("list[dict[str, Any]]", lock_data["package"])

if not locked_packages:
return packages
return repository

for info in locked_packages:
source = info.get("source", {})
Expand All @@ -115,8 +117,9 @@ def locked_repository(self) -> Repository:
if source_type in ["directory", "file"]:
url = self._lock.path.parent.joinpath(url).resolve().as_posix()

name = info["name"]
package = Package(
info["name"],
name,
info["version"],
info["version"],
source_type=source_type,
Expand All @@ -129,9 +132,19 @@ def locked_repository(self) -> Repository:
package.category = info.get("category", "main")
package.optional = info["optional"]
metadata = cast("dict[str, Any]", lock_data["metadata"])
name = info["name"]
if "hashes" in metadata:
# Old lock so we create dummy files from the hashes

# Storing of package files and hashes has been through a few generations in
# the lockfile, we can read them all:
#
# - latest and preferred is that this is read per package, from
# package.files
# - oldest is that hashes were stored in metadata.hashes without filenames
# - in between those two, hashes were stored alongside filenames in
# metadata.files
package_files = info.get("files")
if package_files is not None:
package.files = package_files
elif "hashes" in metadata:
hashes = cast("dict[str, Any]", metadata["hashes"])
package.files = [{"name": h, "hash": h} for h in hashes[name]]
elif source_type in {"git", "directory", "url"}:
Expand Down Expand Up @@ -208,9 +221,9 @@ def locked_repository(self) -> Repository:
if "develop" in info:
package.develop = info["develop"]

packages.add_package(package)
repository.add_package(package)

return packages
return repository

def set_lock_data(self, root: Package, packages: list[Package]) -> bool:
files: dict[str, Any] = table()
Expand All @@ -232,8 +245,6 @@ def set_lock_data(self, root: Package, packages: list[Package]) -> bool:
assert isinstance(package_files, Array)
files[package["name"]] = package_files.multiline(True)

del package["files"]

lock = document()
lock.add(comment(GENERATED_COMMENT))
lock["package"] = package_specs
Expand All @@ -248,7 +259,6 @@ def set_lock_data(self, root: Package, packages: list[Package]) -> bool:
"lock-version": self._VERSION,
"python-versions": root.python_versions,
"content-hash": self._content_hash,
"files": files,
}

if not self.is_locked() or lock != self.lock_data:
Expand Down Expand Up @@ -296,11 +306,7 @@ def _get_lock_data(self) -> TOMLDocument:
metadata = cast("Table", lock_data["metadata"])
lock_version = Version.parse(metadata.get("lock-version", "1.0"))
current_version = Version.parse(self._VERSION)
# We expect the locker to be able to read lock files
# from the same semantic versioning range
accepted_versions = parse_constraint(
f"^{Version.from_parts(current_version.major, 0)}"
)
accepted_versions = parse_constraint(self._READ_VERSION_RANGE)
lock_version_allowed = accepted_versions.allows(lock_version)
if lock_version_allowed and current_version < lock_version:
logger.warning(
Expand Down
24 changes: 12 additions & 12 deletions src/poetry/puzzle/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,18 +572,6 @@ def complete_package(
dependency = dependency_package.dependency
requires = package.requires

if self._load_deferred:
# Retrieving constraints for deferred dependencies
for r in requires:
if r.is_direct_origin():
locked = self.get_locked(r)
# If lock file contains exactly the same URL and reference
# (commit hash) of dependency as is requested,
# do not analyze it again: nothing could have changed.
if locked is not None and locked.package.is_same_package_as(r):
continue
self.search_for_direct_origin_dependency(r)

optional_dependencies = []
_dependencies = []

Expand Down Expand Up @@ -636,6 +624,18 @@ def complete_package(

_dependencies.append(dep)

if self._load_deferred:
# Retrieving constraints for deferred dependencies
for dep in _dependencies:
if dep.is_direct_origin():
locked = self.get_locked(dep)
# If lock file contains exactly the same URL and reference
# (commit hash) of dependency as is requested,
# do not analyze it again: nothing could have changed.
if locked is not None and locked.package.is_same_package_as(dep):
continue
self.search_for_direct_origin_dependency(dep)

dependencies = self._get_dependencies_with_overrides(
_dependencies, dependency_package
)
Expand Down
4 changes: 3 additions & 1 deletion src/poetry/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,7 +1475,9 @@ def run_pip(self, *args: str, **kwargs: Any) -> int | str:
return self._run(cmd, **kwargs)

def run_python_script(self, content: str, **kwargs: Any) -> int | str:
return self.run(self._executable, "-W", "ignore", "-", input_=content, **kwargs)
return self.run(
self._executable, "-I", "-W", "ignore", "-", input_=content, **kwargs
)

def _run(self, cmd: list[str], **kwargs: Any) -> int | str:
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/console/commands/self/test_remove_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def install_plugin(installed: Repository) -> None:
"python-versions": "^3.6",
"platform": "*",
"content-hash": "123456789",
"hashes": {"poetry-plugin": []},
"files": {"poetry-plugin": []},
},
}
system_pyproject_file.parent.joinpath("poetry.lock").write_text(
Expand Down
2 changes: 1 addition & 1 deletion tests/console/commands/test_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def test_lock_no_update(

assert len(packages) == len(locked_repository.packages)

assert locker.lock_data["metadata"].get("lock-version") == "1.1"
assert locker.lock_data["metadata"].get("lock-version") == "2.0"

for package in packages:
assert locked_repository.find_packages(package.to_dependency())
Loading

0 comments on commit 0aea78e

Please sign in to comment.