-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Path based scripts #304
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
Path based scripts #304
Changes from all commits
d961b34
733cd23
ab31d1d
7428858
b9382bf
699bed6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,7 +68,6 @@ def find_files_to_add(self, exclude_build=True): # type: () -> list | |
| Finds all files to add to the tarball | ||
| """ | ||
| excluded = self.find_excluded_files() | ||
| src = self._module.path | ||
| to_add = [] | ||
|
|
||
| for include in self._module.includes: | ||
|
|
@@ -91,14 +90,18 @@ def find_files_to_add(self, exclude_build=True): # type: () -> list | |
| " - Adding: <comment>{}</comment>".format(str(file)), | ||
| verbosity=self._io.VERBOSITY_VERY_VERBOSE, | ||
| ) | ||
| to_add.append(file) | ||
| to_add.append((file, file)) | ||
|
|
||
| _, scripts = self.convert_entry_points() | ||
| for name, script in scripts.items(): | ||
| to_add.append((Path(script), Path("bin") / name)) | ||
|
|
||
| # Include project files | ||
| self._io.writeln( | ||
| " - Adding: <comment>pyproject.toml</comment>", | ||
| verbosity=self._io.VERBOSITY_VERY_VERBOSE, | ||
| ) | ||
| to_add.append(Path("pyproject.toml")) | ||
| to_add.append((Path("pyproject.toml"), Path("pyproject.toml"))) | ||
|
|
||
| # If a license file exists, add it | ||
| for license_file in self._path.glob("LICENSE*"): | ||
|
|
@@ -108,7 +111,8 @@ def find_files_to_add(self, exclude_build=True): # type: () -> list | |
| ), | ||
| verbosity=self._io.VERBOSITY_VERY_VERBOSE, | ||
| ) | ||
| to_add.append(license_file.relative_to(self._path)) | ||
| file_path = license_file.relative_to(self._path) | ||
| to_add.append((file_path, file_path)) | ||
|
|
||
| # If a README is specificed we need to include it | ||
| # to avoid errors | ||
|
|
@@ -121,21 +125,26 @@ def find_files_to_add(self, exclude_build=True): # type: () -> list | |
| ), | ||
| verbosity=self._io.VERBOSITY_VERY_VERBOSE, | ||
| ) | ||
| to_add.append(readme.relative_to(self._path)) | ||
| readme_path = readme.relative_to(self._path) | ||
| to_add.append((readme_path, readme_path)) | ||
|
|
||
| # If a build script is specified and explicitely required | ||
| # we add it to the list of files | ||
| if self._package.build and not exclude_build: | ||
| to_add.append(Path(self._package.build)) | ||
| to_add.append((Path(self._package.build), Path(self._package.build))) | ||
|
|
||
| return sorted(to_add) | ||
|
|
||
| def convert_entry_points(self): # type: () -> dict | ||
| def convert_entry_points(self): # type: () -> (dict, dict) | ||
| result = defaultdict(list) | ||
| scripts = {} | ||
|
|
||
| # Scripts -> Entry points | ||
| for name, ep in self._poetry.local_config.get("scripts", {}).items(): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| result["console_scripts"].append("{} = {}".format(name, ep)) | ||
| if isinstance(ep, dict): | ||
| scripts[name] = ep["path"] | ||
| else: | ||
| result["console_scripts"].append("{} = {}".format(name, ep)) | ||
|
|
||
| # Plugins -> entry points | ||
| plugins = self._poetry.local_config.get("plugins", {}) | ||
|
|
@@ -145,8 +154,7 @@ def convert_entry_points(self): # type: () -> dict | |
|
|
||
| for groupname in result: | ||
| result[groupname] = sorted(result[groupname]) | ||
|
|
||
| return dict(result) | ||
| return dict(result), scripts | ||
|
|
||
| @classmethod | ||
| def convert_author(cls, author): # type: () -> dict | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -107,7 +107,6 @@ def _build(self): | |
|
|
||
| def _copy_module(self, wheel): | ||
| excluded = self.find_excluded_files() | ||
| src = self._module.path | ||
| to_add = [] | ||
|
|
||
| for include in self._module.includes: | ||
|
|
@@ -148,7 +147,7 @@ def _write_metadata(self, wheel): | |
| or "plugins" in self._poetry.local_config | ||
| ): | ||
| with self._write_to_zip(wheel, self.dist_info + "/entry_points.txt") as f: | ||
| self._write_entry_points(f) | ||
| self._write_entry_points(wheel, f) | ||
|
|
||
| for base in ("COPYING", "LICENSE"): | ||
| for path in sorted(self._path.glob(base + "*")): | ||
|
|
@@ -176,6 +175,10 @@ def find_excluded_files(self): # type: () -> list | |
| def dist_info(self): # type: () -> str | ||
| return self.dist_info_name(self._package.name, self._meta.version) | ||
|
|
||
| @property | ||
| def data_info(self): # type: () -> str | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The directory itself is |
||
| return self.data_info_name(self._package.name, self._meta.version) | ||
|
|
||
| @property | ||
| def wheel_filename(self): # type: () -> str | ||
| return "{}-{}-{}.whl".format( | ||
|
|
@@ -195,6 +198,12 @@ def dist_info_name(self, distribution, version): # type: (...) -> str | |
|
|
||
| return "{}-{}.dist-info".format(escaped_name, escaped_version) | ||
|
|
||
| def data_info_name(self, distribution, version): # type: (...) -> str | ||
| escaped_name = re.sub("[^\w\d.]+", "_", distribution, flags=re.UNICODE) | ||
| escaped_version = re.sub("[^\w\d.]+", "_", version, flags=re.UNICODE) | ||
|
|
||
| return "{}-{}.data".format(escaped_name, escaped_version) | ||
|
|
||
| @property | ||
| def tag(self): | ||
| if self._package.build: | ||
|
|
@@ -215,7 +224,7 @@ def tag(self): | |
|
|
||
| return "-".join(tag) | ||
|
|
||
| def _add_file(self, wheel, full_path, rel_path): | ||
| def _add_file(self, wheel, full_path, rel_path, executable=False): | ||
| full_path, rel_path = str(full_path), str(rel_path) | ||
| if os.sep != "/": | ||
| # We always want to have /-separated paths in the zip file and in | ||
|
|
@@ -226,7 +235,7 @@ def _add_file(self, wheel, full_path, rel_path): | |
|
|
||
| # Normalize permission bits to either 755 (executable) or 644 | ||
| st_mode = os.stat(full_path).st_mode | ||
| new_mode = normalize_file_permissions(st_mode) | ||
| new_mode = normalize_file_permissions(st_mode, executable=executable) | ||
| zinfo.external_attr = (new_mode & 0xFFFF) << 16 # Unix attributes | ||
|
|
||
| if stat.S_ISDIR(st_mode): | ||
|
|
@@ -265,11 +274,11 @@ def _write_to_zip(self, wheel, rel_path): | |
| wheel.writestr(zi, b, compress_type=zipfile.ZIP_DEFLATED) | ||
| self._records.append((rel_path, hash_digest, len(b))) | ||
|
|
||
| def _write_entry_points(self, fp): | ||
| def _write_entry_points(self, wheel, fp): | ||
| """ | ||
| Write entry_points.txt. | ||
| """ | ||
| entry_points = self.convert_entry_points() | ||
| entry_points, scripts = self.convert_entry_points() | ||
|
|
||
| for group_name in sorted(entry_points): | ||
| fp.write("[{}]\n".format(group_name)) | ||
|
|
@@ -278,6 +287,12 @@ def _write_entry_points(self, fp): | |
|
|
||
| fp.write("\n") | ||
|
|
||
| for name, script in scripts.items(): | ||
| full_path = self._original_path / script | ||
| self._add_file( | ||
| wheel, full_path, self.data_info + "/scripts/" + name, executable=True | ||
| ) | ||
|
|
||
| def _write_wheel_file(self, fp): | ||
| fp.write( | ||
| wheel_file_template.format( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fail with newer pip which creates and installs a wheel from the source distribution and supports pyproject.toml. Since
pyproject.tomlstill refers to the original path of the script, it will fail since those would not exist in the sdist.One approach to fix this may be to include the original file with the original path in the source distribution and then in the generated setup.py we can copy those files to a temporary directory with the correct name (since setuptools does not provide a facility for mapping to a different name in the
scriptskey) and then pass those paths in thescriptslist tosetup().Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also using
relative_tolike below would be good since it would reject values like"../other-project/bin/script".convert_entry_pointswill need to return absolute paths for scripts in order for this to behave as expected.