Skip to content

Commit a056c46

Browse files
authored
builder: fix file exclusion with source root
Previously when a file was included via package inclusion, and the source root differed from the project root, these files were not correctly excluded when ignored by the vcs. This change resolves the issue by ensuring the project root is used when identifying exclusions.
1 parent d5bb41a commit a056c46

File tree

11 files changed

+127
-11
lines changed

11 files changed

+127
-11
lines changed

poetry/core/masonry/builders/builder.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def __init__(
4646
self._poetry = poetry
4747
self._package = poetry.package
4848
self._path = poetry.file.parent
49-
self._original_path = self._path
5049
self._excluded_files = None
5150
self._executable = Path(executable or sys.executable) # type: Path
5251

@@ -99,7 +98,7 @@ def build(self):
9998
def find_excluded_files(self): # type: () -> Set[str]
10099
if self._excluded_files is None:
101100
# Checking VCS
102-
vcs = get_vcs(self._original_path)
101+
vcs = get_vcs(self._path)
103102
if not vcs:
104103
vcs_ignored_files = set()
105104
else:
@@ -158,7 +157,9 @@ def find_files_to_add(
158157
if self.format in formats:
159158
for current_file in file.glob("**/*"):
160159
include_file = BuildIncludeFile(
161-
path=current_file, source_root=self._path
160+
path=current_file,
161+
project_root=self._path,
162+
source_root=self._path,
162163
)
163164

164165
if not current_file.is_dir() and not self.is_excluded(
@@ -176,10 +177,12 @@ def find_files_to_add(
176177
else:
177178
source_root = self._path
178179

179-
include_file = BuildIncludeFile(path=file, source_root=source_root)
180+
include_file = BuildIncludeFile(
181+
path=file, project_root=self._path, source_root=source_root
182+
)
180183

181184
if self.is_excluded(
182-
include_file.relative_to_source_root()
185+
include_file.relative_to_project_root()
183186
) and isinstance(include, PackageInclude):
184187
continue
185188

@@ -197,13 +200,15 @@ def find_files_to_add(
197200
if self._package.build_script and not exclude_build:
198201
to_add.add(
199202
BuildIncludeFile(
200-
path=self._package.build_script, source_root=self._path
203+
path=self._package.build_script,
204+
project_root=self._path,
205+
source_root=self._path,
201206
)
202207
)
203208

204209
return to_add
205210

206-
def get_metadata_content(self): # type: () -> bytes
211+
def get_metadata_content(self): # type: () -> str
207212
content = METADATA_BASE.format(
208213
name=self._meta.name,
209214
version=self._meta.version,
@@ -310,14 +315,17 @@ def temporary_directory(cls, *args, **kwargs):
310315
class BuildIncludeFile:
311316
def __init__(
312317
self,
313-
path, # type: Path
314-
source_root=None, # type: Optional[Path]
318+
path, # type: Union[Path, str]
319+
project_root, # type: Union[Path, str]
320+
source_root=None, # type: Optional[Union[Path, str]]
315321
):
316322
"""
323+
:param project_root: the full path of the project's root
317324
:param path: a full path to the file to be included
318325
:param source_root: the root path to resolve to
319326
"""
320327
self.path = Path(path)
328+
self.project_root = Path(project_root).resolve()
321329
self.source_root = None if not source_root else Path(source_root).resolve()
322330
if not self.path.is_absolute() and self.source_root:
323331
self.path = self.source_root / self.path
@@ -346,6 +354,9 @@ def __hash__(self):
346354
def __repr__(self): # type: () -> str
347355
return str(self.path)
348356

357+
def relative_to_project_root(self): # type(): -> Path
358+
return self.path.relative_to(self.project_root)
359+
349360
def relative_to_source_root(self): # type(): -> Path
350361
if self.source_root is not None:
351362
return self.path.relative_to(self.source_root)

poetry/core/masonry/builders/sdist.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,9 @@ def find_files_to_add(
319319
additional_files.add(self._poetry.local_config["readme"])
320320

321321
for file in additional_files:
322-
file = BuildIncludeFile(path=file, source_root=self._path)
322+
file = BuildIncludeFile(
323+
path=file, project_root=self._path, source_root=self._path
324+
)
323325
if file.path.exists():
324326
logger.debug("Adding: {}".format(file.relative_to_source_root()))
325327
to_add.add(file)

poetry/core/masonry/builders/wheel.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def _write_metadata(self, wheel):
188188
relative_path = "%s/%s" % (self.dist_info, path.relative_to(self._path))
189189
self._add_file(wheel, path, relative_path)
190190
else:
191-
logger.debug("Skipping: %s", path.as_posix())
191+
logger.debug("Skipping: {}".format(path.as_posix()))
192192

193193
with self._write_to_zip(wheel, self.dist_info + "/WHEEL") as f:
194194
self._write_wheel_file(f)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2018 Sébastien Eustace
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
My Package
2+
==========
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[tool.poetry]
2+
name = "my-package"
3+
version = "1.2.3"
4+
description = "Some description."
5+
authors = [
6+
"Sébastien Eustace <[email protected]>"
7+
]
8+
license = "MIT"
9+
10+
readme = "README.rst"
11+
12+
homepage = "https://python-poetry.org/"
13+
repository = "https://github.com/python-poetry/poetry"
14+
documentation = "https://python-poetry.org/docs"
15+
16+
keywords = ["packaging", "dependency", "poetry"]
17+
18+
classifiers = [
19+
"Topic :: Software Development :: Build Tools",
20+
"Topic :: Software Development :: Libraries :: Python Modules"
21+
]
22+
23+
# Requirements
24+
[tool.poetry.dependencies]
25+
python = "^3.6"
26+
cleo = "^0.6"
27+
cachy = { version = "^0.2.0", extras = ["msgpack"] }
28+
29+
pendulum = { version = "^1.4", optional = true }
30+
31+
[tool.poetry.dev-dependencies]
32+
pytest = "~3.4"
33+
34+
[tool.poetry.extras]
35+
time = ["pendulum"]
36+
37+
[tool.poetry.scripts]
38+
my-script = "my_package:main"
39+
my-2nd-script = "my_package:main2"

tests/masonry/builders/fixtures/default_src_with_excluded_data/src/my_package/__init__.py

Whitespace-only changes.

tests/masonry/builders/fixtures/default_src_with_excluded_data/src/my_package/data/data1.txt

Whitespace-only changes.

tests/masonry/builders/fixtures/default_src_with_excluded_data/src/my_package/data/sub_data/data2.txt

Whitespace-only changes.

tests/masonry/builders/fixtures/default_src_with_excluded_data/src/my_package/data/sub_data/data3.txt

Whitespace-only changes.

tests/masonry/builders/test_wheel.py

+42
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from poetry.core.factory import Factory
88
from poetry.core.masonry.builders.wheel import WheelBuilder
99
from poetry.core.utils._compat import Path
10+
from tests.masonry.builders.test_sdist import project
1011

1112

1213
fixtures_dir = Path(__file__).parent / "fixtures"
@@ -228,3 +229,44 @@ def test_wheel_with_file_with_comma():
228229
with zipfile.ZipFile(str(whl)) as z:
229230
records = z.read("comma_file-1.2.3.dist-info/RECORD")
230231
assert '\n"comma_file/a,b.py"' in records.decode()
232+
233+
234+
def test_default_src_with_excluded_data(mocker):
235+
# Patch git module to return specific excluded files
236+
p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files")
237+
p.return_value = [
238+
(
239+
(
240+
Path(__file__).parent
241+
/ "fixtures"
242+
/ "default_src_with_excluded_data"
243+
/ "src"
244+
/ "my_package"
245+
/ "data"
246+
/ "sub_data"
247+
/ "data2.txt"
248+
)
249+
.relative_to(project("default_src_with_excluded_data"))
250+
.as_posix()
251+
)
252+
]
253+
poetry = Factory().create_poetry(project("default_src_with_excluded_data"))
254+
255+
builder = WheelBuilder(poetry)
256+
builder.build()
257+
258+
whl = (
259+
fixtures_dir
260+
/ "default_src_with_excluded_data"
261+
/ "dist"
262+
/ "my_package-1.2.3-py3-none-any.whl"
263+
)
264+
265+
assert whl.exists()
266+
267+
with zipfile.ZipFile(str(whl)) as z:
268+
names = z.namelist()
269+
assert "my_package/__init__.py" in names
270+
assert "my_package/data/data1.txt" in names
271+
assert "my_package/data/sub_data/data2.txt" not in names
272+
assert "my_package/data/sub_data/data3.txt" in names

0 commit comments

Comments
 (0)