-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathhelpers.py
220 lines (163 loc) · 6.19 KB
/
helpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from __future__ import annotations
import os
import shutil
import urllib.parse
from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from poetry.core.masonry.utils.helpers import escape_name
from poetry.core.masonry.utils.helpers import escape_version
from poetry.core.packages.package import Package
from poetry.core.packages.utils.link import Link
from poetry.core.toml.file import TOMLFile
from poetry.core.vcs.git import ParsedUrl
from poetry.console.application import Application
from poetry.factory import Factory
from poetry.installation.executor import Executor
from poetry.packages import Locker
from poetry.repositories import Repository
from poetry.repositories.exceptions import PackageNotFound
from poetry.utils._compat import WINDOWS
if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.types import DependencyTypes
from poetry.core.semver.version import Version
from tomlkit.toml_document import TOMLDocument
from poetry.installation.operations import OperationTypes
from poetry.poetry import Poetry
FIXTURE_PATH = Path(__file__).parent / "fixtures"
def get_package(name: str, version: str | Version) -> Package:
return Package(name, version)
def get_dependency(
name: str,
constraint: str | dict[str, Any] | None = None,
groups: list[str] | None = None,
optional: bool = False,
allows_prereleases: bool = False,
) -> DependencyTypes:
if constraint is None:
constraint = "*"
if isinstance(constraint, str):
constraint = {"version": constraint}
constraint["optional"] = optional
constraint["allow_prereleases"] = allows_prereleases
return Factory.create_dependency(name, constraint or "*", groups=groups)
def fixture(path: str | None = None) -> Path:
if path:
return FIXTURE_PATH / path
else:
return FIXTURE_PATH
def copy_or_symlink(source: Path, dest: Path) -> None:
if dest.exists():
if dest.is_symlink():
os.unlink(str(dest))
elif dest.is_dir():
shutil.rmtree(str(dest))
else:
os.unlink(str(dest))
# Python2 does not support os.symlink on Windows whereas Python3 does.
# os.symlink requires either administrative privileges or developer mode on Win10,
# throwing an OSError if neither is active.
if WINDOWS:
try:
os.symlink(str(source), str(dest), target_is_directory=source.is_dir())
except OSError:
if source.is_dir():
shutil.copytree(str(source), str(dest))
else:
shutil.copyfile(str(source), str(dest))
else:
os.symlink(str(source), str(dest))
def mock_clone(_: Any, source: str, dest: Path) -> None:
# Checking source to determine which folder we need to copy
parsed = ParsedUrl.parse(source)
folder = (
Path(__file__).parent
/ "fixtures"
/ "git"
/ parsed.resource
/ parsed.pathname.lstrip("/").rstrip(".git")
)
copy_or_symlink(folder, dest)
def mock_download(url: str, dest: str, **__: Any) -> None:
parts = urllib.parse.urlparse(url)
fixtures = Path(__file__).parent / "fixtures"
fixture = fixtures / parts.path.lstrip("/")
copy_or_symlink(fixture, Path(dest))
class TestExecutor(Executor):
def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self._installs = []
self._updates = []
self._uninstalls = []
@property
def installations(self) -> list[Package]:
return self._installs
@property
def updates(self) -> list[Package]:
return self._updates
@property
def removals(self) -> list[Package]:
return self._uninstalls
def _do_execute_operation(self, operation: OperationTypes) -> None:
super()._do_execute_operation(operation)
if not operation.skipped:
getattr(self, f"_{operation.job_type}s").append(operation.package)
def _execute_install(self, operation: OperationTypes) -> int:
return 0
def _execute_update(self, operation: OperationTypes) -> int:
return 0
def _execute_remove(self, operation: OperationTypes) -> int:
return 0
class PoetryTestApplication(Application):
def __init__(self, poetry: Poetry):
super().__init__()
self._poetry = poetry
def reset_poetry(self) -> None:
poetry = self._poetry
self._poetry = Factory().create_poetry(self._poetry.file.path.parent)
self._poetry.set_pool(poetry.pool)
self._poetry.set_config(poetry.config)
self._poetry.set_locker(
TestLocker(poetry.locker.lock.path, self._poetry.local_config)
)
class TestLocker(Locker):
def __init__(self, lock: str | Path, local_config: dict):
self._lock = TOMLFile(lock)
self._local_config = local_config
self._lock_data = None
self._content_hash = self._get_content_hash()
self._locked = False
self._lock_data = None
self._write = False
def write(self, write: bool = True) -> None:
self._write = write
def is_locked(self) -> bool:
return self._locked
def locked(self, is_locked: bool = True) -> TestLocker:
self._locked = is_locked
return self
def mock_lock_data(self, data: dict) -> None:
self.locked()
self._lock_data = data
def is_fresh(self) -> bool:
return True
def _write_lock_data(self, data: TOMLDocument) -> None:
if self._write:
super()._write_lock_data(data)
self._locked = True
return
self._lock_data = data
class TestRepository(Repository):
def find_packages(self, dependency: Dependency) -> list[Package]:
packages = super().find_packages(dependency)
if len(packages) == 0:
raise PackageNotFound(f"Package [{dependency.name}] not found.")
return packages
def find_links_for_package(self, package: Package) -> list[Link]:
return [
Link(
f"https://foo.bar/files/{escape_name(package.name)}"
f"-{escape_version(package.version.text)}-py2.py3-none-any.whl"
)
]