Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-poetry for openSUSE:Factory checked in at 2026-01-21 14:14:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-poetry (Old) and /work/SRC/openSUSE:Factory/.python-poetry.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-poetry" Wed Jan 21 14:14:40 2026 rev:38 rq:1327736 version:2.2.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-poetry/python-poetry.changes 2025-08-20 13:26:31.307416302 +0200 +++ /work/SRC/openSUSE:Factory/.python-poetry.new.1928/python-poetry.changes 2026-01-21 14:15:03.241088282 +0100 @@ -1,0 +2,30 @@ +Fri Jan 16 10:09:38 UTC 2026 - Nico Krapp <[email protected]> + +- Update to 2.2.1 + * Fix an issue where poetry self show failed with a message about an invalid + output format + * Remove outdated statements about dependency groups +- Update to 2.2.0 + * Add support for nesting dependency groups + * Add support for PEP 735 dependency groups + * Add support for PEP 639 license clarity + * Add a --format option to poetry show to alternatively output json format + * Add official support for Python 3.14 + * Normalize dependency group names + * Change installer.no-binary and installer.only-binary so that explicit + package names will take precedence over :all: + * Improve log output during poetry install when a wheel is built from source + * Improve error message in case a file lock could not be acquired while + cloning a git repository + * Require dulwich>=0.24.0 + * Allow virtualenv>=20.33 again + * Allow findpython>=0.7 + * Allow importlib-metadata>=8.7 + * Fix an issue where poetry new did not create the project structure in an + existing empty directory + * Fix an issue where a dependency that was required for a specific Python + version was not installed into an environment of a pre-release Python + version +- Add support-dulwich-0_25.patch to support new dulwich version + +------------------------------------------------------------------- Old: ---- poetry-2.1.4.tar.gz New: ---- poetry-2.2.1.tar.gz support-dulwich-0_25.patch ----------(New B)---------- New: version - Add support-dulwich-0_25.patch to support new dulwich version ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-poetry.spec ++++++ --- /var/tmp/diff_new_pack.BvmsIl/_old 2026-01-21 14:15:04.813156486 +0100 +++ /var/tmp/diff_new_pack.BvmsIl/_new 2026-01-21 14:15:04.817156660 +0100 @@ -1,8 +1,7 @@ # # spec file for package python-poetry # -# Copyright (c) 2025 SUSE LLC -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -28,28 +27,30 @@ %{?sle15_python_module_pythons} Name: python-poetry%{psuffix} -Version: 2.1.4 +Version: 2.2.1 Release: 0 Summary: Python dependency management and packaging License: MIT URL: https://python-poetry.org/ # PyPI sdist doesn't contain tests Source: https://github.com/python-poetry/poetry/archive/%{version}.tar.gz#/poetry-%{version}.tar.gz +# PATCH-FIX-UPSTREAM support-dulwich-0_25.patch gh#python-poetry/poetry#10674 +Patch0: support-dulwich-0_25.patch BuildRequires: %{python_module base >= 3.9} BuildRequires: %{python_module pip} BuildRequires: %{python_module poetry-core >= 2.1} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-poetry-core = 2.1.3 +Requires: python-poetry-core = 2.2.1 Requires: (python-build >= 1.2.1 with python-build < 2.0.0) Requires: (python-cachecontrol >= 0.14.0 with python-cachecontrol < 0.15.0) # from cachecontrol[filecache] Requires: python-filelock >= 3.8.0 # /cachecontrol[filecache] Requires: (python-cleo >= 2.1.0 with python-cleo < 3.0.0) -Requires: python-packaging >= 24.0 +Requires: python-packaging >= 24.2 Requires: python-trove-classifiers >= 2022.5.19 -Requires: (python-dulwich >= 0.22.6 with python-dulwich < 0.23.0) +Requires: (python-dulwich >= 0.25.0 with python-dulwich < 0.26.0) Requires: (python-fastjsonschema >= 2.18.0 with python-fastjsonschema < 3.0.0) Requires: (python-installer >= 0.7.0 with python-installer < 0.8.0) Requires: (python-keyring >= 25.1.0 with python-keyring < 26.0.0) @@ -61,9 +62,9 @@ Requires: (python-shellingham >= 1.5 with python-shellingham < 2.0) # allow findpython 0.7.0 https://github.com/python-poetry/poetry/issues/10468 Requires: (python-findpython >= 0.6.2 with python-findpython < 0.8.0) +Requires: python-virtualenv >= 20.26.6 Requires: (python-pbs-installer >= 2025.1.6 with python-pbs-installer < 2026.0.0) Requires: (python-tomlkit >= 0.11.4 with python-tomlkit < 1.0.0) -Requires: (python-virtualenv >= 20.26.6 with python-virtualenv < 20.33.0) # python-pbs-installer[download,install] Requires: (python-httpx >= 0.27.0 with python-httpx < 1) Requires: python-zstandard >= 0.21.0 ++++++ poetry-2.1.4.tar.gz -> poetry-2.2.1.tar.gz ++++++ ++++ 8458 lines of diff (skipped) ++++++ support-dulwich-0_25.patch ++++++ >From 2b0723c277cb2a51c8b030e02e0830eeefc75632 Mon Sep 17 00:00:00 2001 From: David Hotham <[email protected]> Date: Mon, 29 Dec 2025 22:51:23 +0000 Subject: [PATCH] Dulwich upgrade (#10674) --- poetry.lock | 76 ++++++++++++------------ pyproject.toml | 2 +- src/poetry/vcs/git/backend.py | 78 +++++++++++++++---------- tests/integration/test_utils_vcs_git.py | 31 ++++++---- tests/vcs/git/conftest.py | 3 + tests/vcs/git/test_backend.py | 14 ++--- 6 files changed, 116 insertions(+), 88 deletions(-) Index: poetry-2.2.1/pyproject.toml =================================================================== --- poetry-2.2.1.orig/pyproject.toml +++ poetry-2.2.1/pyproject.toml @@ -8,7 +8,7 @@ dependencies = [ "build (>=1.2.1,<2.0.0)", "cachecontrol[filecache] (>=0.14.0,<0.15.0)", "cleo (>=2.1.0,<3.0.0)", - "dulwich (>=0.24.0,<0.25.0)", + "dulwich (>=0.25.0,<0.26.0)", "fastjsonschema (>=2.18.0,<3.0.0)", "importlib-metadata (>=4.4) ; python_version < '3.10'", "installer (>=0.7.0,<0.8.0)", Index: poetry-2.2.1/src/poetry/vcs/git/backend.py =================================================================== --- poetry-2.2.1.orig/src/poetry/vcs/git/backend.py +++ poetry-2.2.1/src/poetry/vcs/git/backend.py @@ -20,7 +20,9 @@ from dulwich.config import parse_submodu from dulwich.errors import NotGitRepository from dulwich.file import FileLocked from dulwich.index import IndexEntry -from dulwich.refs import ANNOTATED_TAG_SUFFIX +from dulwich.objects import ObjectID +from dulwich.protocol import PEELED_TAG_SUFFIX +from dulwich.refs import Ref from dulwich.repo import Repo from poetry.console.exceptions import PoetryRuntimeError @@ -76,10 +78,10 @@ def is_revision_sha(revision: str | None return re.match(r"^\b[0-9a-f]{5,40}\b$", revision or "") is not None -def annotated_tag(ref: str | bytes) -> bytes: +def peeled_tag(ref: str | bytes) -> Ref: if isinstance(ref, str): ref = ref.encode("utf-8") - return ref + ANNOTATED_TAG_SUFFIX + return Ref(ref + PEELED_TAG_SUFFIX) @dataclasses.dataclass @@ -87,7 +89,7 @@ class GitRefSpec: branch: str | None = None revision: str | None = None tag: str | None = None - ref: bytes = dataclasses.field(default_factory=lambda: b"HEAD") + ref: Ref = dataclasses.field(default_factory=lambda: Ref(b"HEAD")) def resolve(self, remote_refs: FetchPackResult, repo: Repo) -> None: """ @@ -104,7 +106,7 @@ class GitRefSpec: """ if self.revision: ref = f"refs/tags/{self.revision}".encode() - if ref in remote_refs.refs or annotated_tag(ref) in remote_refs.refs: + if ref in remote_refs.refs or peeled_tag(ref) in remote_refs.refs: # this is a tag, incorrectly specified as a revision, tags take priority self.tag = self.revision self.revision = None @@ -120,7 +122,7 @@ class GitRefSpec: and f"refs/heads/{self.branch}".encode() not in remote_refs.refs and ( f"refs/tags/{self.branch}".encode() in remote_refs.refs - or annotated_tag(f"refs/tags/{self.branch}") in remote_refs.refs + or peeled_tag(f"refs/tags/{self.branch}") in remote_refs.refs ) ): # this is a tag incorrectly specified as a branch @@ -131,7 +133,7 @@ class GitRefSpec: # revision is a short sha, resolve to full sha short_sha = self.revision.encode("utf-8") for sha in remote_refs.refs.values(): - if sha.startswith(short_sha): + if sha is not None and sha.startswith(short_sha): self.revision = sha.decode("utf-8") return @@ -145,24 +147,25 @@ class GitRefSpec: Internal helper method to populate ref and set it's sha as the remote's head and default ref. """ - self.ref = remote_refs.symrefs[b"HEAD"] + self.ref = remote_refs.symrefs[Ref(b"HEAD")] + head: ObjectID | None if self.revision: - head = self.revision.encode("utf-8") + head = ObjectID(self.revision.encode("utf-8")) else: if self.tag: - ref = f"refs/tags/{self.tag}".encode() - annotated = annotated_tag(ref) - self.ref = annotated if annotated in remote_refs.refs else ref + ref = Ref(f"refs/tags/{self.tag}".encode()) + peeled = peeled_tag(ref) + self.ref = peeled if peeled in remote_refs.refs else ref elif self.branch: self.ref = ( - self.branch.encode("utf-8") + Ref(self.branch.encode("utf-8")) if self.is_ref - else f"refs/heads/{self.branch}".encode() + else Ref(f"refs/heads/{self.branch}".encode()) ) head = remote_refs.refs[self.ref] - remote_refs.refs[self.ref] = remote_refs.refs[b"HEAD"] = head + remote_refs.refs[self.ref] = remote_refs.refs[Ref(b"HEAD")] = head @property def key(self) -> str: @@ -216,7 +219,7 @@ class Git: @staticmethod def get_revision(repo: Repo) -> str: with repo: - return repo.get_peeled(b"HEAD").decode("utf-8") + return repo.get_peeled(Ref(b"HEAD")).decode("utf-8") @classmethod def info(cls, repo: Repo | Path) -> GitRepoLocalInfo: @@ -234,21 +237,24 @@ class Git: client: GitClient path: str - kwargs: dict[str, str] = {} credentials = get_default_authenticator().get_credentials_for_git_url(url=url) + username = None + password = None if credentials.password and credentials.username: # we do this conditionally as otherwise, dulwich might complain if these # parameters are passed in for an ssh url - kwargs["username"] = credentials.username - kwargs["password"] = credentials.password + username = credentials.username + password = credentials.password config = local.get_config_stack() - client, path = get_transport_and_path(url, config=config, **kwargs) + client, path = get_transport_and_path( + url, config=config, username=username, password=password + ) with local: result: FetchPackResult = client.fetch( - path, + path.encode(), local, determine_wants=local.object_store.determine_wants_all, ) @@ -335,7 +341,9 @@ class Git: try: # ensure local HEAD matches remote - local.refs[b"HEAD"] = remote_refs.refs[b"HEAD"] + ref = remote_refs.refs[Ref(b"HEAD")] + if ref is not None: + local.refs[Ref(b"HEAD")] = ref except ValueError: raise PoetryRuntimeError.create( reason=f"<error>Failed to clone {url} at '{refspec.key}', verify ref exists on remote.</>", @@ -349,30 +357,36 @@ class Git: if refspec.is_ref: # set ref to current HEAD - local.refs[refspec.ref] = local.refs[b"HEAD"] + local.refs[refspec.ref] = local.refs[Ref(b"HEAD")] for base, prefix in { - (b"refs/remotes/origin", b"refs/heads/"), - (b"refs/tags", b"refs/tags"), + (Ref(b"refs/remotes/origin"), b"refs/heads/"), + (Ref(b"refs/tags"), b"refs/tags"), }: try: local.refs.import_refs( base=base, other={ - n[len(prefix) :]: v + Ref(n[len(prefix) :]): v for (n, v) in remote_refs.refs.items() - if n.startswith(prefix) and not n.endswith(ANNOTATED_TAG_SUFFIX) + if n.startswith(prefix) + and not n.endswith(PEELED_TAG_SUFFIX) + and v is not None }, ) except FileLocked as e: - def to_str(path: bytes) -> str: - return path.decode().replace(os.sep * 2, os.sep) + def to_str(path: bytes | str) -> str: + if isinstance(path, bytes): + path = path.decode() + return path.replace(os.sep * 2, os.sep) raise PoetryRuntimeError.create( + # <https://github.com/jelmer/dulwich/pull/2045> should clean up the + # ignore. reason=( f"<error>Failed to clone {url} at '{refspec.key}'," - f" unable to acquire file lock for {to_str(e.filename)}.</>" + f" unable to acquire file lock for {to_str(e.filename)}.</>" # type: ignore[arg-type] ), info=[ ERROR_MESSAGE_NOTE, @@ -519,7 +533,9 @@ class Git: with current_repo: # we use peeled sha here to ensure tags are resolved consistently - current_sha = current_repo.get_peeled(b"HEAD").decode("utf-8") + current_sha = current_repo.get_peeled(Ref(b"HEAD")).decode( + "utf-8" + ) except (NotGitRepository, AssertionError, KeyError): # something is wrong with the current checkout, clean it remove_directory(target, force=True) Index: poetry-2.2.1/tests/integration/test_utils_vcs_git.py =================================================================== --- poetry-2.2.1.orig/tests/integration/test_utils_vcs_git.py +++ poetry-2.2.1/tests/integration/test_utils_vcs_git.py @@ -15,7 +15,9 @@ import pytest from dulwich.client import HTTPUnauthorized from dulwich.client import get_transport_and_path +from dulwich.config import CaseInsensitiveOrderedMultiDict from dulwich.config import ConfigFile +from dulwich.refs import Ref from dulwich.repo import Repo from poetry.console.exceptions import PoetryConsoleError @@ -108,7 +110,9 @@ def _remote_refs(source_url: str, local_ path: str client, path = get_transport_and_path(source_url) return client.fetch( - path, local_repo, determine_wants=local_repo.object_store.determine_wants_all + path.encode(), + local_repo, + determine_wants=local_repo.object_store.determine_wants_all, ) @@ -118,8 +122,8 @@ def remote_refs(_remote_refs: FetchPackR @pytest.fixture(scope="module") -def remote_default_ref(_remote_refs: FetchPackResult) -> bytes: - ref: bytes = _remote_refs.symrefs[b"HEAD"] +def remote_default_ref(_remote_refs: FetchPackResult) -> Ref: + ref: Ref = _remote_refs.symrefs[Ref(b"HEAD")] return ref @@ -136,12 +140,14 @@ def test_use_system_git_client_from_envi def test_git_local_info( - source_url: str, remote_refs: FetchPackResult, remote_default_ref: bytes + source_url: str, remote_refs: FetchPackResult, remote_default_ref: Ref ) -> None: with Git.clone(url=source_url) as repo: info = Git.info(repo=repo) assert info.origin == source_url - assert info.revision == remote_refs.refs[remote_default_ref].decode("utf-8") + ref = remote_refs.refs[remote_default_ref] + assert ref is not None + assert info.revision == ref.decode("utf-8") @pytest.mark.parametrize( @@ -151,7 +157,7 @@ def test_git_clone_default_branch_head( specification: GitCloneKwargs, source_url: str, remote_refs: FetchPackResult, - remote_default_ref: bytes, + remote_default_ref: Ref, mocker: MockerFixture, ) -> None: spy = mocker.spy(Git, "_clone") @@ -294,7 +300,7 @@ def test_system_git_fallback_on_http_401 mocker.patch.object( Git, "_clone", - side_effect=HTTPUnauthorized(None, None), + side_effect=HTTPUnauthorized(None, source_url), ) # use tmp_path for source_root to get a shorter path, @@ -307,7 +313,7 @@ def test_system_git_fallback_on_http_401 spy.assert_called_with( url="https://github.com/python-poetry/test-fixture-vcs-repository.git", target=path, - refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"), + refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=Ref(b"HEAD")), ) spy.assert_called_once() @@ -388,6 +394,8 @@ def test_username_password_parameter_is_ spy_get_transport_and_path.assert_called_with( location=source_url, config=dummy_git_config, + username=None, + password=None, ) spy_get_transport_and_path.assert_called_once() @@ -411,7 +419,7 @@ def test_system_git_called_when_configur spy_legacy.assert_called_with( url=source_url, target=path, - refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"), + refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=Ref(b"HEAD")), ) @@ -428,9 +436,10 @@ def test_relative_submodules_with_ssh( ) # construct fake git config - fake_config = ConfigFile( - {(b"remote", b"origin"): {b"url": ssh_source_url.encode("utf-8")}} + values = CaseInsensitiveOrderedMultiDict.make( + {b"url": ssh_source_url.encode("utf-8")} ) + fake_config = ConfigFile({(b"remote", b"origin"): values}) # trick Git into thinking remote.origin is an ssh url mock_get_config = mocker.patch.object(repo_with_unresolved_submodules, "get_config") mock_get_config.return_value = fake_config Index: poetry-2.2.1/tests/vcs/git/conftest.py =================================================================== --- poetry-2.2.1.orig/tests/vcs/git/conftest.py +++ poetry-2.2.1/tests/vcs/git/conftest.py @@ -27,6 +27,7 @@ def temp_repo(tmp_path: Path) -> TempRep author=b"User <[email protected]>", message=b"init", no_verify=True, + sign=False, ) # one commit which is not "head" @@ -37,6 +38,7 @@ def temp_repo(tmp_path: Path) -> TempRep author=b"User <[email protected]>", message=b"extra", no_verify=True, + sign=False, ) # extra commit @@ -48,6 +50,7 @@ def temp_repo(tmp_path: Path) -> TempRep author=b"User <[email protected]>", message=b"extra", no_verify=True, + sign=False, ) repo[b"refs/tags/v1"] = head_commit Index: poetry-2.2.1/tests/vcs/git/test_backend.py =================================================================== --- poetry-2.2.1.orig/tests/vcs/git/test_backend.py +++ poetry-2.2.1/tests/vcs/git/test_backend.py @@ -11,7 +11,7 @@ from dulwich.repo import Repo from poetry.console.exceptions import PoetryRuntimeError from poetry.vcs.git.backend import Git -from poetry.vcs.git.backend import annotated_tag +from poetry.vcs.git.backend import peeled_tag from poetry.vcs.git.backend import is_revision_sha from poetry.vcs.git.backend import urlpathjoin @@ -60,8 +60,8 @@ def test_get_name_from_source_url(url: s @pytest.mark.parametrize(("tag"), ["my-tag", b"my-tag"]) -def test_annotated_tag(tag: str | bytes) -> None: - tag = annotated_tag("my-tag") +def test_peeled_tag(tag: str | bytes) -> None: + tag = peeled_tag("my-tag") assert tag == b"my-tag^{}"
