Skip to content

Commit

Permalink
Simplify/improve Package.clone() (#159)
Browse files Browse the repository at this point in the history
Downstream clients (e.g., poetry) appear to assume that the result
of a Package.clone() will be a full-fidelity copy of the original.

Use `copy.deepcopy` to clone the object, and ensure that this is
the case.

Resolves Issue #2422

Co-authored-by: Nicolas Simonds <nisimond@cisco.com>
  • Loading branch information
0xDEC0DE and nisimond authored Apr 29, 2021
1 parent fe476e0 commit 3f718c5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 27 deletions.
29 changes: 2 additions & 27 deletions poetry/core/packages/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,33 +428,8 @@ def without_features(self) -> "Package":
return self.with_features([])

def clone(self) -> "Package":
if self.is_root():
clone = self.__class__(self.pretty_name, self.version)
else:
clone = self.__class__(
self.pretty_name,
self.version,
source_type=self._source_type,
source_url=self._source_url,
source_reference=self._source_reference,
features=list(self.features),
)

clone.description = self.description
clone.category = self.category
clone.optional = self.optional
clone.python_versions = self.python_versions
clone.marker = self.marker
clone.extras = self.extras
clone.root_dir = self.root_dir
clone.develop = self.develop

for dep in self.requires:
clone.requires.append(dep)

for dep in self.dev_requires:
clone.dev_requires.append(dep)

clone = self.__class__(self.pretty_name, self.version)
clone.__dict__ = copy.deepcopy(self.__dict__)
return clone

def __hash__(self) -> int:
Expand Down
29 changes: 29 additions & 0 deletions tests/packages/test_package.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import unicode_literals

import random

from pathlib import Path

import pytest
Expand Down Expand Up @@ -280,3 +282,30 @@ def test_to_dependency_for_url():
assert "https://example.com/path.tar.gz" == dep.url
assert "url" == dep.source_type
assert "https://example.com/path.tar.gz" == dep.source_url


def test_package_clone(f):
# TODO(nic): this test is not future-proof, in that any attributes added
# to the Package object and not filled out in this test setup might
# cause comparisons to match that otherwise should not. A factory method
# to create a Package object with all fields fully randomized would be the
# most rigorous test for this, but that's likely overkill.
p = Package(
"lol_wut",
"3.141.5926535",
pretty_version="③.⑭.⑮",
source_type="git",
source_url="http://some.url",
source_reference="fe4d2adabf3feb5d32b70ab5c105285fa713b10c",
source_resolved_reference="fe4d2adabf3feb5d32b70ab5c105285fa713b10c",
features=["abc", "def"],
develop=random.choice((True, False)),
)
p.files = (["file1", "file2", "file3"],)
p.homepage = "https://some.other.url"
p.repository_url = "http://bug.farm"
p.documentation_url = "http://lorem.ipsum/dolor/sit.amet"
p2 = p.clone()

assert p == p2
assert p.__dict__ == p2.__dict__

0 comments on commit 3f718c5

Please sign in to comment.