Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of inline tables in include on pyproject.toml. #6

Merged
merged 4 commits into from
Apr 26, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,18 @@ def create_poetry(self, cwd=None): # type: (Optional[Path]) -> Poetry
package.build_config = build or {}

if "include" in local_config:
package.include = local_config["include"]
package.include = []

for include in local_config["include"]:
if not isinstance(include, dict):
include = {"path": include}

formats = include.get("format", [])
abn marked this conversation as resolved.
Show resolved Hide resolved
if formats and not isinstance(formats, list):
formats = [formats]
include["format"] = formats

package.include.append(include)

if "exclude" in local_config:
package.exclude = local_config["exclude"]
Expand Down
49 changes: 41 additions & 8 deletions poetry/core/json/schemas/poetry-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,43 @@
],
"properties": {
"include": {
"type": "string",
"description": "What to include in the package."
"$ref": "#/definitions/include-path"
},
"from": {
"type": "string",
"description": "Where the source directory of the package resides."
},
"format": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
],
"description": "The format(s) for which the package must be included."
"$ref": "#/definitions/package-formats"
}
}
}
},
"include": {
"type": "array",
"description": "A list of files and folders to include."
"description": "A list of files and folders to include.",
"items": {
"anyOf": [
{
"$ref": "#/definitions/include-path"
},
{
"type": "object",
"additionalProperties": false,
"required": [
"path"
],
"properties": {
"path": {
"$ref": "#/definitions/include-path"
},
"format": {
kasteph marked this conversation as resolved.
Show resolved Hide resolved
"$ref": "#/definitions/package-formats"
}
}
}
]
}
},
"exclude": {
"type": "array",
Expand Down Expand Up @@ -189,6 +206,22 @@
"type": "string"
}
},
"include-path": {
"type": "string",
"description": "Path to file or directory to include."
},
"package-format": {
"type": "string",
"enum": ["sdist", "wheel"],
"description": "A Python packaging format."
},
"package-formats": {
"oneOf": [
{"$ref": "#/definitions/package-format"},
{"type": "array", "items": {"$ref": "#/definitions/package-format"}}
],
"description": "The format(s) for which the package must be included."
},
"dependencies": {
"type": "object",
"patternProperties": {
Expand Down
121 changes: 94 additions & 27 deletions poetry/core/masonry/builders/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from collections import defaultdict
from contextlib import contextmanager
from typing import Optional
from typing import Set
from typing import Union

Expand Down Expand Up @@ -60,12 +61,27 @@ def __init__(

packages.append(p)

includes = []
for include in self._package.include:
formats = include.get("format", [])

if (
formats
and self.format
and self.format not in formats
and not ignore_packages_formats
):
continue

includes.append(include)

self._module = Module(
self._package.name,
self._path.as_posix(),
packages=packages,
includes=self._package.include,
includes=includes,
)

self._meta = Metadata.from_package(self._package)

def build(self):
Expand Down Expand Up @@ -113,23 +129,49 @@ def is_excluded(self, filepath): # type: (Union[str, Path]) -> bool

return False

def find_files_to_add(self, exclude_build=True): # type: (bool) -> list
def find_files_to_add(
self, exclude_build=True
): # type: (bool) -> Set[BuildIncludeFile]
"""
Finds all files to add to the tarball
"""
to_add = []
to_add = set()

for include in self._module.includes:
include.refresh()
formats = include.formats or ["sdist"]
abn marked this conversation as resolved.
Show resolved Hide resolved

for file in include.elements:
if "__pycache__" in str(file):
continue

if file.is_dir():
if self.format in formats:
for current_file in file.glob("**/*"):
include_file = BuildIncludeFile(
path=current_file, source_root=self._path
)

if not current_file.is_dir() and not self.is_excluded(
include_file.relative_to_source_root()
):
to_add.add(include_file)
continue

file = file.relative_to(self._path)
if (
isinstance(include, PackageInclude)
and include.source
and self.format == "wheel"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dist specific logic should probably move to specific classes.

):
source_root = include.base
else:
source_root = self._path

include_file = BuildIncludeFile(path=file, source_root=source_root)

if self.is_excluded(file) and isinstance(include, PackageInclude):
if self.is_excluded(
include_file.relative_to_source_root()
) and isinstance(include, PackageInclude):
continue

if file.suffix == ".pyc":
Expand All @@ -140,31 +182,19 @@ def find_files_to_add(self, exclude_build=True): # type: (bool) -> list
continue

logger.debug(" - Adding: {}".format(str(file)))
to_add.append(file)

# Include project files
logger.debug(" - Adding: pyproject.toml")
to_add.append(Path("pyproject.toml"))

# If a license file exists, add it
for license_file in self._path.glob("LICENSE*"):
logger.debug(" - Adding: {}".format(license_file.relative_to(self._path)))
to_add.append(license_file.relative_to(self._path))

# If a README is specified we need to include it
# to avoid errors
if "readme" in self._poetry.local_config:
readme = self._path / self._poetry.local_config["readme"]
if readme.exists():
logger.debug(" - Adding: {}".format(readme.relative_to(self._path)))
to_add.append(readme.relative_to(self._path))

# If a build script is specified and explicitely required
to_add.add(include_file)

# If a build script is specified and explicitly required
# we add it to the list of files
if self._package.build_script and not exclude_build:
to_add.append(Path(self._package.build_script))
to_add.add(
BuildIncludeFile(
path=self._path / self._package.build_script,
source_root=self._path,
)
)

return sorted(to_add)
return to_add

def get_metadata_content(self): # type: () -> bytes
content = METADATA_BASE.format(
Expand Down Expand Up @@ -268,3 +298,40 @@ def temporary_directory(cls, *args, **kwargs):
yield name

shutil.rmtree(name)


class BuildIncludeFile:
def __init__(
self,
path, # type: Path
source_root=None, # type: Optional[Path]
):
"""
:param path: a full path to the file to be included
:param source_root: the root path to resolve to
"""
self.path = Path(path)
self.source_root = None if not source_root else Path(source_root).resolve()
if not self.path.is_absolute() and self.source_root:
self.path = (self.source_root / self.path).resolve()
else:
self.path = self.path.resolve()

def __eq__(self, other): # type: (Union[BuildIncludeFile, Path]) -> bool
if hasattr(other, "path"):
return self.path == other.path
return self.path == other

def __ne__(self, other): # type: (Union[BuildIncludeFile, Path]) -> bool
kasteph marked this conversation as resolved.
Show resolved Hide resolved
return not self.__eq__(other)

def __hash__(self):
return hash(self.path)

def __repr__(self): # type: () -> str
return str(self.path)

def relative_to_source_root(self): # type(): -> Path
if self.source_root is not None:
return self.path.relative_to(self.source_root)
return self.path
40 changes: 35 additions & 5 deletions poetry/core/masonry/builders/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from posixpath import join as pjoin
from pprint import pformat
from typing import Iterator
from typing import List

from poetry.core.utils._compat import Path
from poetry.core.utils._compat import decode
Expand All @@ -22,6 +23,7 @@
from ..utils.helpers import normalize_file_permissions
from ..utils.package_include import PackageInclude
from .builder import Builder
from .builder import BuildIncludeFile


SETUP = """\
Expand Down Expand Up @@ -74,15 +76,15 @@ def build(self, target_dir=None): # type: (Path) -> Path

files_to_add = self.find_files_to_add(exclude_build=False)

for relpath in files_to_add:
path = self._path / relpath
for file in files_to_add:
tar_info = tar.gettarinfo(
str(path), arcname=pjoin(tar_dir, str(relpath))
str(file.path),
arcname=pjoin(tar_dir, str(file.relative_to_source_root())),
)
tar_info = self.clean_tarinfo(tar_info)

if tar_info.isreg():
with path.open("rb") as f:
with file.path.open("rb") as f:
tar.addfile(tar_info, f)
else:
tar.addfile(tar_info) # Symlinks & ?
Expand All @@ -105,7 +107,6 @@ def build(self, target_dir=None): # type: (Path) -> Path
gz.close()

logger.info(" - Built <comment>{}</comment>".format(target.name))

return target

def build_setup(self): # type: () -> bytes
Expand Down Expand Up @@ -302,6 +303,35 @@ def find_nearest_pkg(rel_path):

return pkgdir, sorted(packages), pkg_data

def find_files_to_add(
self, exclude_build=False
): # type: (bool) -> List[BuildIncludeFile]
to_add = super(SdistBuilder, self).find_files_to_add(exclude_build)

# Include project files
logger.debug(" - Adding: pyproject.toml")
to_add.add(
BuildIncludeFile(path=self._path / "pyproject.toml", source_root=self._path)
)

# If a license file exists, add it
abn marked this conversation as resolved.
Show resolved Hide resolved
for license_file in self._path.glob("LICENSE*"):
license_file = BuildIncludeFile(path=license_file, source_root=self._path)
logger.debug(" - Adding: {}".format(license_file.relative_to_source_root()))
to_add.add(license_file)

# If a README is specified we need to include it to avoid errors
if "readme" in self._poetry.local_config:
readme = BuildIncludeFile(
path=self._path / self._poetry.local_config["readme"],
source_root=self._path,
)
if readme.path.exists():
logger.debug(" - Adding: {}".format(readme.relative_to_source_root()))
to_add.add(readme)

return sorted(list(to_add), key=lambda x: x.relative_to_source_root())

@classmethod
def convert_dependencies(cls, package, dependencies):
main = []
Expand Down
Loading