"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "poetry/masonry/builders/editable.py" between
poetry-1.1.15.tar.gz and poetry-1.2.0.tar.gz

About: Poetry is a tool for dependency management and packaging in Python.

editable.py  (poetry-1.1.15):editable.py  (poetry-1.2.0)
from __future__ import unicode_literals from __future__ import annotations
import csv
import hashlib import hashlib
import json
import os import os
import shutil import shutil
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
from pathlib import Path
from typing import TYPE_CHECKING
from poetry.core.masonry.builders.builder import Builder from poetry.core.masonry.builders.builder import Builder
from poetry.core.masonry.builders.sdist import SdistBuilder from poetry.core.masonry.builders.sdist import SdistBuilder
from poetry.core.masonry.utils.package_include import PackageInclude from poetry.core.masonry.utils.package_include import PackageInclude
from poetry.core.semver.version import Version from poetry.core.semver.version import Version
from poetry.utils._compat import WINDOWS from poetry.utils._compat import WINDOWS
from poetry.utils._compat import Path
from poetry.utils._compat import decode from poetry.utils._compat import decode
from poetry.utils.env import build_environment
from poetry.utils.helpers import is_dir_writable from poetry.utils.helpers import is_dir_writable
from poetry.utils.pip import pip_install
if TYPE_CHECKING:
from cleo.io.io import IO
from poetry.poetry import Poetry
from poetry.utils.env import Env
SCRIPT_TEMPLATE = """\ SCRIPT_TEMPLATE = """\
#!{python} #!{python}
import sys
from {module} import {callable_holder} from {module} import {callable_holder}
if __name__ == '__main__': if __name__ == '__main__':
{callable_}() sys.exit({callable_}())
""" """
WINDOWS_CMD_TEMPLATE = """\ WINDOWS_CMD_TEMPLATE = """\
@echo off\r\n"{python}" "%~dp0\\{script}" %*\r\n @echo off\r\n"{python}" "%~dp0\\{script}" %*\r\n
""" """
class EditableBuilder(Builder): class EditableBuilder(Builder):
def __init__(self, poetry, env, io): def __init__(self, poetry: Poetry, env: Env, io: IO) -> None:
super(EditableBuilder, self).__init__(poetry) super().__init__(poetry)
self._env = env self._env = env
self._io = io self._io = io
def build(self): def build(self, target_dir: Path | None = None) -> Path:
self._debug( self._debug(
" - Building package <c1>{}</c1> in <info>editable</info> mode".for f" - Building package <c1>{self._package.name}</c1> in"
mat( " <info>editable</info> mode"
self._package.name
)
) )
if self._package.build_script: if self._package.build_script:
if self._package.build_should_generate_setup(): if self._package.build_should_generate_setup():
self._debug( self._debug(
" - <warning>Falling back on using a <b>setup.py</b></warni ng>" " - <warning>Falling back on using a <b>setup.py</b></warni ng>"
) )
self._setup_build()
return self._setup_build() path: Path = self._path
return path
self._run_build_script(self._package.build_script) self._run_build_script(self._package.build_script)
for removed in self._env.site_packages.remove_distribution_files(
distribution_name=self._package.name
):
self._debug(
f" - Removed <c2>{removed.name}</c2> directory from"
f" <b>{removed.parent}</b>"
)
added_files = [] added_files = []
added_files += self._add_pth() added_files += self._add_pth()
added_files += self._add_scripts() added_files += self._add_scripts()
self._add_dist_info(added_files) self._add_dist_info(added_files)
def _run_build_script(self, build_script): path = self._path
self._debug(" - Executing build script: <b>{}</b>".format(build_script) return path
)
self._env.run("python", str(self._path.joinpath(build_script)), call=Tru def _run_build_script(self, build_script: str) -> None:
e) with build_environment(poetry=self._poetry, env=self._env, io=self._io)
as env:
self._debug(f" - Executing build script: <b>{build_script}</b>")
env.run("python", str(self._path.joinpath(build_script)), call=True)
def _setup_build(self): def _setup_build(self) -> None:
builder = SdistBuilder(self._poetry) builder = SdistBuilder(self._poetry)
setup = self._path / "setup.py" setup = self._path / "setup.py"
has_setup = setup.exists() has_setup = setup.exists()
if has_setup: if has_setup:
self._io.write_line( self._io.write_error_line(
"<warning>A setup.py file already exists. Using it.</warning>" "<warning>A setup.py file already exists. Using it.</warning>"
) )
else: else:
with setup.open("w", encoding="utf-8") as f: with setup.open("w", encoding="utf-8") as f:
f.write(decode(builder.build_setup())) f.write(decode(builder.build_setup()))
try: try:
if self._env.pip_version < Version(19, 0): if self._env.pip_version < Version.from_parts(19, 0):
self._env.run_pip("install", "-e", str(self._path), "--no-deps") pip_install(self._path, self._env, upgrade=True, editable=True)
else: else:
# Temporarily rename pyproject.toml # Temporarily rename pyproject.toml
shutil.move( shutil.move(
str(self._poetry.file), str(self._poetry.file.with_suffix(". tmp")) str(self._poetry.file), str(self._poetry.file.with_suffix(". tmp"))
) )
try: try:
self._env.run_pip("install", "-e", str(self._path), "--no-de ps") pip_install(self._path, self._env, upgrade=True, editable=Tr ue)
finally: finally:
shutil.move( shutil.move(
str(self._poetry.file.with_suffix(".tmp")), str(self._poetry.file.with_suffix(".tmp")),
str(self._poetry.file), str(self._poetry.file),
) )
finally: finally:
if not has_setup: if not has_setup:
os.remove(str(setup)) os.remove(str(setup))
def _add_pth(self): def _add_pth(self) -> list[Path]:
paths = set() paths = {
for include in self._module.includes: include.base.resolve().as_posix()
if isinstance(include, PackageInclude) and ( for include in self._module.includes
include.is_module() or include.is_package() if isinstance(include, PackageInclude)
): and (include.is_module() or include.is_package())
paths.add(include.base.resolve().as_posix()) }
content = ""
for path in paths:
content += decode(path + os.linesep)
content = "".join(decode(path + os.linesep) for path in paths)
pth_file = Path(self._module.name).with_suffix(".pth") pth_file = Path(self._module.name).with_suffix(".pth")
# remove any pre-existing pth files for this package
for file in self._env.site_packages.find(path=pth_file, writable_only=Tr
ue):
self._debug(
f" - Removing existing <c2>{file.name}</c2> from <b>{file.paren
t}</b>"
f" for {self._poetry.file.parent}"
)
# We can't use unlink(missing_ok=True) because it's not always avail
able
if file.exists():
file.unlink()
try: try:
pth_file = self._env.site_packages.write_text( pth_file = self._env.site_packages.write_text(
pth_file, content, encoding="utf-8" pth_file, content, encoding="utf-8"
) )
self._debug( self._debug(
" - Adding <c2>{}</c2> to <b>{}</b> for {}".format( f" - Adding <c2>{pth_file.name}</c2> to <b>{pth_file.parent}</b
pth_file.name, pth_file.parent, self._poetry.file.parent > for"
) f" {self._poetry.file.parent}"
) )
return [pth_file] return [pth_file]
except OSError: except OSError:
# TODO: Replace with PermissionError # TODO: Replace with PermissionError
self._io.error_line( self._io.write_error_line(
" - Failed to create <c2>{}</c2> for {}".format( f" - Failed to create <c2>{pth_file.name}</c2> for"
pth_file.name, self._poetry.file.parent f" {self._poetry.file.parent}"
)
) )
return [] return []
def _add_scripts(self): def _add_scripts(self) -> list[Path]:
added = [] added = []
entry_points = self.convert_entry_points() entry_points = self.convert_entry_points()
for scripts_path in self._env.script_dirs: for scripts_path in self._env.script_dirs:
if is_dir_writable(path=scripts_path, create=True): if is_dir_writable(path=scripts_path, create=True):
break break
else: else:
self._io.error_line( self._io.write_error_line(
" - Failed to find a suitable script installation directory for " - Failed to find a suitable script installation directory for
{}".format( "
self._poetry.file.parent f" {self._poetry.file.parent}"
)
) )
return [] return []
scripts = entry_points.get("console_scripts", []) scripts = entry_points.get("console_scripts", [])
for script in scripts: for script in scripts:
name, script = script.split(" = ") name, script = script.split(" = ")
module, callable_ = script.split(":") module, callable_ = script.split(":")
callable_holder = callable_.split(".", 1)[0] callable_holder = callable_.split(".", 1)[0]
script_file = scripts_path.joinpath(name) script_file = scripts_path.joinpath(name)
self._debug( self._debug(
" - Adding the <c2>{}</c2> script to <b>{}</b>".format( f" - Adding the <c2>{name}</c2> script to <b>{scripts_path}</b>
name, scripts_path "
)
) )
with script_file.open("w", encoding="utf-8") as f: with script_file.open("w", encoding="utf-8") as f:
f.write( f.write(
decode( decode(
SCRIPT_TEMPLATE.format( SCRIPT_TEMPLATE.format(
python=self._env.python, python=self._env.python,
module=module, module=module,
callable_holder=callable_holder, callable_holder=callable_holder,
callable_=callable_, callable_=callable_,
) )
skipping to change at line 174 skipping to change at line 202
) )
script_file.chmod(0o755) script_file.chmod(0o755)
added.append(script_file) added.append(script_file)
if WINDOWS: if WINDOWS:
cmd_script = script_file.with_suffix(".cmd") cmd_script = script_file.with_suffix(".cmd")
cmd = WINDOWS_CMD_TEMPLATE.format(python=self._env.python, scrip t=name) cmd = WINDOWS_CMD_TEMPLATE.format(python=self._env.python, scrip t=name)
self._debug( self._debug(
" - Adding the <c2>{}</c2> script wrapper to <b>{}</b>".for f" - Adding the <c2>{cmd_script.name}</c2> script wrapper t
mat( o"
cmd_script.name, scripts_path f" <b>{scripts_path}</b>"
)
) )
with cmd_script.open("w", encoding="utf-8") as f: with cmd_script.open("w", encoding="utf-8") as f:
f.write(decode(cmd)) f.write(decode(cmd))
added.append(cmd_script) added.append(cmd_script)
return added return added
def _add_dist_info(self, added_files): def _add_dist_info(self, added_files: list[Path]) -> None:
from poetry.core.masonry.builders.wheel import WheelBuilder from poetry.core.masonry.builders.wheel import WheelBuilder
added_files = added_files[:] added_files = added_files[:]
builder = WheelBuilder(self._poetry) builder = WheelBuilder(self._poetry)
dist_info = self._env.site_packages.mkdir(Path(builder.dist_info))
dist_info_path = Path(builder.dist_info)
for dist_info in self._env.site_packages.find(
dist_info_path, writable_only=True
):
if dist_info.exists():
self._debug(
" - Removing existing <c2>{}</c2> directory from <b>{}</b>"
.format(
dist_info.name, dist_info.parent
)
)
shutil.rmtree(str(dist_info))
dist_info = self._env.site_packages.mkdir(dist_info_path)
self._debug( self._debug(
" - Adding the <c2>{}</c2> directory to <b>{}</b>".format( f" - Adding the <c2>{dist_info.name}</c2> directory to"
dist_info.name, dist_info.parent f" <b>{dist_info.parent}</b>"
)
) )
with dist_info.joinpath("METADATA").open("w", encoding="utf-8") as f: with dist_info.joinpath("METADATA").open("w", encoding="utf-8") as f:
builder._write_metadata_file(f) builder._write_metadata_file(f)
added_files.append(dist_info.joinpath("METADATA")) added_files.append(dist_info.joinpath("METADATA"))
with dist_info.joinpath("INSTALLER").open("w", encoding="utf-8") as f: with dist_info.joinpath("INSTALLER").open("w", encoding="utf-8") as f:
f.write("poetry") f.write("poetry")
added_files.append(dist_info.joinpath("INSTALLER")) added_files.append(dist_info.joinpath("INSTALLER"))
if self.convert_entry_points(): if self.convert_entry_points():
with dist_info.joinpath("entry_points.txt").open( with dist_info.joinpath("entry_points.txt").open(
"w", encoding="utf-8" "w", encoding="utf-8"
) as f: ) as f:
builder._write_entry_points(f) builder._write_entry_points(f)
added_files.append(dist_info.joinpath("entry_points.txt")) added_files.append(dist_info.joinpath("entry_points.txt"))
with dist_info.joinpath("RECORD").open("w", encoding="utf-8") as f: # write PEP 610 metadata
direct_url_json = dist_info.joinpath("direct_url.json")
direct_url_json.write_text(
json.dumps(
{
"dir_info": {"editable": True},
"url": self._poetry.file.path.parent.as_uri(),
}
)
)
added_files.append(direct_url_json)
record = dist_info.joinpath("RECORD")
with record.open("w", encoding="utf-8", newline="") as f:
csv_writer = csv.writer(f)
for path in added_files: for path in added_files:
hash = self._get_file_hash(path) hash = self._get_file_hash(path)
size = path.stat().st_size size = path.stat().st_size
f.write("{},sha256={},{}\n".format(str(path), hash, size)) csv_writer.writerow((path, f"sha256={hash}", size))
# RECORD itself is recorded with no hash or size # RECORD itself is recorded with no hash or size
f.write("{},,\n".format(dist_info.joinpath("RECORD"))) csv_writer.writerow((record, "", ""))
def _get_file_hash(self, filepath): def _get_file_hash(self, filepath: Path) -> str:
hashsum = hashlib.sha256() hashsum = hashlib.sha256()
with filepath.open("rb") as src: with filepath.open("rb") as src:
while True: while True:
buf = src.read(1024 * 8) buf = src.read(1024 * 8)
if not buf: if not buf:
break break
hashsum.update(buf) hashsum.update(buf)
src.seek(0) src.seek(0)
return urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") return urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=")
def _debug(self, msg): def _debug(self, msg: str) -> None:
if self._io.is_debug(): if self._io.is_debug():
self._io.write_line(msg) self._io.write_line(msg)
 End of changes. 37 change blocks. 
77 lines changed or deleted 106 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)