init.py (poetry-1.1.15) | : | init.py (poetry-1.2.0) | ||
---|---|---|---|---|
# -*- coding: utf-8 -*- | from __future__ import annotations | |||
from __future__ import unicode_literals | ||||
import os | ||||
import re | ||||
import sys | import sys | |||
from pathlib import Path | ||||
from typing import TYPE_CHECKING | ||||
from typing import Any | ||||
from typing import Dict | from typing import Dict | |||
from typing import List | from typing import Mapping | |||
from typing import Tuple | ||||
from typing import Union | from typing import Union | |||
from cleo import option | from cleo.helpers import option | |||
from packaging.utils import canonicalize_name | ||||
from tomlkit import inline_table | from tomlkit import inline_table | |||
from poetry.core.pyproject import PyProjectException | from poetry.console.commands.command import Command | |||
from poetry.core.pyproject.toml import PyProjectTOML | from poetry.console.commands.env_command import EnvCommand | |||
from poetry.utils._compat import OrderedDict | from poetry.utils.dependency_specification import parse_dependency_specification | |||
from poetry.utils._compat import Path | ||||
from poetry.utils._compat import urlparse | if TYPE_CHECKING: | |||
from packaging.utils import NormalizedName | ||||
from poetry.core.packages.package import Package | ||||
from tomlkit.items import InlineTable | ||||
from .command import Command | from poetry.repositories import Pool | |||
from .env_command import EnvCommand | ||||
Requirements = Dict[str, Union[str, Mapping[str, Any]]] | ||||
class InitCommand(Command): | class InitCommand(Command): | |||
name = "init" | name = "init" | |||
description = ( | description = ( | |||
"Creates a basic <comment>pyproject.toml</> file in the current director y." | "Creates a basic <comment>pyproject.toml</> file in the current director y." | |||
) | ) | |||
options = [ | options = [ | |||
option("name", None, "Name of the package.", flag=False), | option("name", None, "Name of the package.", flag=False), | |||
option("description", None, "Description of the package.", flag=False), | option("description", None, "Description of the package.", flag=False), | |||
skipping to change at line 56 | skipping to change at line 60 | |||
None, | None, | |||
"Package to require for development, with an optional version constr aint, " | "Package to require for development, with an optional version constr aint, " | |||
"e.g. requests:^2.10.0 or requests=2.11.1.", | "e.g. requests:^2.10.0 or requests=2.11.1.", | |||
flag=False, | flag=False, | |||
multiple=True, | multiple=True, | |||
), | ), | |||
option("license", "l", "License of the package.", flag=False), | option("license", "l", "License of the package.", flag=False), | |||
] | ] | |||
help = """\ | help = """\ | |||
The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the | The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the | |||
current directory. | \ | |||
current directory. | ||||
""" | """ | |||
def __init__(self): | def __init__(self) -> None: | |||
super(InitCommand, self).__init__() | super().__init__() | |||
self._pool: Pool | None = None | ||||
self._pool = None | def handle(self) -> int: | |||
from pathlib import Path | ||||
def handle(self): | from poetry.core.pyproject.toml import PyProjectTOML | |||
from poetry.core.vcs.git import GitConfig | from poetry.core.vcs.git import GitConfig | |||
from poetry.layouts import layout | from poetry.layouts import layout | |||
from poetry.utils._compat import Path | ||||
from poetry.utils.env import SystemEnv | from poetry.utils.env import SystemEnv | |||
pyproject = PyProjectTOML(Path.cwd() / "pyproject.toml") | pyproject = PyProjectTOML(Path.cwd() / "pyproject.toml") | |||
if pyproject.file.exists(): | if pyproject.file.exists(): | |||
if pyproject.is_poetry_project(): | if pyproject.is_poetry_project(): | |||
self.line( | self.line_error( | |||
"<error>A pyproject.toml file with a poetry section already | "<error>A pyproject.toml file with a poetry section already" | |||
exists.</error>" | " exists.</error>" | |||
) | ) | |||
return 1 | return 1 | |||
if pyproject.data.get("build-system"): | if pyproject.data.get("build-system"): | |||
self.line( | self.line_error( | |||
"<error>A pyproject.toml file with a defined build-system al | "<error>A pyproject.toml file with a defined build-system al | |||
ready exists.</error>" | ready" | |||
" exists.</error>" | ||||
) | ) | |||
return 1 | return 1 | |||
vcs_config = GitConfig() | vcs_config = GitConfig() | |||
self.line("") | if self.io.is_interactive(): | |||
self.line( | self.line("") | |||
"This command will guide you through creating your <info>pyproject.t | self.line( | |||
oml</> config." | "This command will guide you through creating your" | |||
) | " <info>pyproject.toml</> config." | |||
self.line("") | ) | |||
self.line("") | ||||
name = self.option("name") | name = self.option("name") | |||
if not name: | if not name: | |||
name = Path.cwd().name.lower() | name = Path.cwd().name.lower() | |||
question = self.create_question( | question = self.create_question( | |||
"Package name [<comment>{}</comment>]: ".format(name), default=n ame | f"Package name [<comment>{name}</comment>]: ", default=name | |||
) | ) | |||
name = self.ask(question) | name = self.ask(question) | |||
version = "0.1.0" | version = "0.1.0" | |||
question = self.create_question( | question = self.create_question( | |||
"Version [<comment>{}</comment>]: ".format(version), default=version | f"Version [<comment>{version}</comment>]: ", default=version | |||
) | ) | |||
version = self.ask(question) | version = self.ask(question) | |||
description = self.option("description") or "" | description = self.option("description") | |||
question = self.create_question( | if not description: | |||
"Description [<comment>{}</comment>]: ".format(description), | description = self.ask(self.create_question("Description []: ", defa | |||
default=description, | ult="")) | |||
) | ||||
description = self.ask(question) | ||||
author = self.option("author") | author = self.option("author") | |||
if not author and vcs_config and vcs_config.get("user.name"): | if not author and vcs_config.get("user.name"): | |||
author = vcs_config["user.name"] | author = vcs_config["user.name"] | |||
author_email = vcs_config.get("user.email") | author_email = vcs_config.get("user.email") | |||
if author_email: | if author_email: | |||
author += " <{}>".format(author_email) | author += f" <{author_email}>" | |||
question = self.create_question( | question = self.create_question( | |||
"Author [<comment>{}</comment>, n to skip]: ".format(author), defaul t=author | f"Author [<comment>{author}</comment>, n to skip]: ", default=author | |||
) | ) | |||
question.set_validator(lambda v: self._validate_author(v, author)) | question.set_validator(lambda v: self._validate_author(v, author)) | |||
author = self.ask(question) | author = self.ask(question) | |||
if not author: | if not author: | |||
authors = [] | authors = [] | |||
else: | else: | |||
authors = [author] | authors = [author] | |||
license = self.option("license") or "" | license = self.option("license") | |||
if not license: | ||||
question = self.create_question( | license = self.ask(self.create_question("License []: ", default="")) | |||
"License [<comment>{}</comment>]: ".format(license), default=license | ||||
) | ||||
question.set_validator(self._validate_license) | ||||
license = self.ask(question) | ||||
python = self.option("python") | python = self.option("python") | |||
if not python: | if not python: | |||
current_env = SystemEnv(Path(sys.executable)) | current_env = SystemEnv(Path(sys.executable)) | |||
default_python = "^{}".format( | default_python = "^" + ".".join( | |||
".".join(str(v) for v in current_env.version_info[:2]) | str(v) for v in current_env.version_info[:2] | |||
) | ) | |||
question = self.create_question( | question = self.create_question( | |||
"Compatible Python versions [<comment>{}</comment>]: ".format( | f"Compatible Python versions [<comment>{default_python}</comment | |||
default_python | >]: ", | |||
), | ||||
default=default_python, | default=default_python, | |||
) | ) | |||
python = self.ask(question) | python = self.ask(question) | |||
self.line("") | if self.io.is_interactive(): | |||
self.line("") | ||||
requirements = {} | requirements: Requirements = {} | |||
if self.option("dependency"): | if self.option("dependency"): | |||
requirements = self._format_requirements( | requirements = self._format_requirements( | |||
self._determine_requirements(self.option("dependency")) | self._determine_requirements(self.option("dependency")) | |||
) | ) | |||
question = "Would you like to define your main dependencies interactivel y?" | question = "Would you like to define your main dependencies interactivel y?" | |||
help_message = ( | help_message = """\ | |||
"You can specify a package in the following forms:\n" | You can specify a package in the following forms: | |||
" - A single name (<b>requests</b>)\n" | - A single name (<b>requests</b>): this will search for matches on PyPI | |||
" - A name and a constraint (<b>requests@^2.23.0</b>)\n" | - A name and a constraint (<b>requests@^2.23.0</b>) | |||
" - A git url (<b>git+https://github.com/python-poetry/poetry.git</ | - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>) | |||
b>)\n" | - A git url with a revision\ | |||
" - A git url with a revision (<b>git+https://github.com/python-poe | (<b>git+https://github.com/python-poetry/poetry.git#develop</b>) | |||
try/poetry.git#develop</b>)\n" | - A file path (<b>../my-package/my-package.whl</b>) | |||
" - A file path (<b>../my-package/my-package.whl</b>)\n" | - A directory (<b>../my-package/</b>) | |||
" - A directory (<b>../my-package/</b>)\n" | - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>) | |||
" - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz< | """ | |||
/b>)\n" | ||||
) | ||||
help_displayed = False | help_displayed = False | |||
if self.confirm(question, True): | if self.confirm(question, True): | |||
self.line(help_message) | if self.io.is_interactive(): | |||
help_displayed = True | self.line(help_message) | |||
help_displayed = True | ||||
requirements.update( | requirements.update( | |||
self._format_requirements(self._determine_requirements([])) | self._format_requirements(self._determine_requirements([])) | |||
) | ) | |||
self.line("") | if self.io.is_interactive(): | |||
self.line("") | ||||
dev_requirements = {} | dev_requirements: Requirements = {} | |||
if self.option("dev-dependency"): | if self.option("dev-dependency"): | |||
dev_requirements = self._format_requirements( | dev_requirements = self._format_requirements( | |||
self._determine_requirements(self.option("dev-dependency")) | self._determine_requirements(self.option("dev-dependency")) | |||
) | ) | |||
question = ( | question = ( | |||
"Would you like to define your development dependencies interactivel y?" | "Would you like to define your development dependencies interactivel y?" | |||
) | ) | |||
if self.confirm(question, True): | if self.confirm(question, True): | |||
if not help_displayed: | if self.io.is_interactive() and not help_displayed: | |||
self.line(help_message) | self.line(help_message) | |||
dev_requirements.update( | dev_requirements.update( | |||
self._format_requirements(self._determine_requirements([])) | self._format_requirements(self._determine_requirements([])) | |||
) | ) | |||
self.line("") | if self.io.is_interactive(): | |||
self.line("") | ||||
layout_ = layout("standard")( | layout_ = layout("standard")( | |||
name, | name, | |||
version, | version, | |||
description=description, | description=description, | |||
author=authors[0] if authors else None, | author=authors[0] if authors else None, | |||
license=license, | license=license, | |||
python=python, | python=python, | |||
dependencies=requirements, | dependencies=requirements, | |||
dev_dependencies=dev_requirements, | dev_dependencies=dev_requirements, | |||
) | ) | |||
content = layout_.generate_poetry_content(original=pyproject) | content = layout_.generate_poetry_content() | |||
for section in content: | ||||
pyproject.data.append(section, content[section]) | ||||
if self.io.is_interactive(): | if self.io.is_interactive(): | |||
self.line("<info>Generated file</info>") | self.line("<info>Generated file</info>") | |||
self.line("") | self.line("") | |||
self.line(content) | self.line(pyproject.data.as_string().replace("\r\n", "\n")) | |||
self.line("") | self.line("") | |||
if not self.confirm("Do you confirm generation?", True): | if not self.confirm("Do you confirm generation?", True): | |||
self.line("<error>Command aborted</error>") | self.line_error("<error>Command aborted</error>") | |||
return 1 | return 1 | |||
with (Path.cwd() / "pyproject.toml").open("w", encoding="utf-8") as f: | pyproject.save() | |||
f.write(content) | ||||
return 0 | ||||
def _generate_choice_list( | ||||
self, matches: list[Package], canonicalized_name: NormalizedName | ||||
) -> list[str]: | ||||
choices = [] | ||||
matches_names = [p.name for p in matches] | ||||
exact_match = canonicalized_name in matches_names | ||||
if exact_match: | ||||
choices.append(matches[matches_names.index(canonicalized_name)].pret | ||||
ty_name) | ||||
for found_package in matches: | ||||
if len(choices) >= 10: | ||||
break | ||||
if found_package.name == canonicalized_name: | ||||
continue | ||||
choices.append(found_package.pretty_name) | ||||
return choices | ||||
def _determine_requirements( | def _determine_requirements( | |||
self, requires, allow_prereleases=False, source=None | self, | |||
): # type: (List[str], bool) -> List[Dict[str, str]] | requires: list[str], | |||
allow_prereleases: bool = False, | ||||
source: str | None = None, | ||||
) -> list[dict[str, Any]]: | ||||
if not requires: | if not requires: | |||
requires = [] | result = [] | |||
package = self.ask( | question = self.create_question( | |||
"Search for package to add (or leave blank to continue):" | "Package to add or search for (leave blank to skip):" | |||
) | ) | |||
while package is not None: | question.set_validator(self._validate_package) | |||
package = self.ask(question) | ||||
while package: | ||||
constraint = self._parse_requirements([package])[0] | constraint = self._parse_requirements([package])[0] | |||
if ( | if ( | |||
"git" in constraint | "git" in constraint | |||
or "url" in constraint | or "url" in constraint | |||
or "path" in constraint | or "path" in constraint | |||
or "version" in constraint | or "version" in constraint | |||
): | ): | |||
self.line("Adding <info>{}</info>".format(package)) | self.line(f"Adding <info>{package}</info>") | |||
requires.append(constraint) | result.append(constraint) | |||
package = self.ask("\nAdd a package:") | package = self.ask("\nAdd a package (leave blank to skip):") | |||
continue | continue | |||
matches = self._get_pool().search(constraint["name"]) | canonicalized_name = canonicalize_name(constraint["name"]) | |||
matches = self._get_pool().search(canonicalized_name) | ||||
if not matches: | if not matches: | |||
self.line("<error>Unable to find package</error>") | self.line_error("<error>Unable to find package</error>") | |||
package = False | package = False | |||
else: | else: | |||
choices = [] | choices = self._generate_choice_list(matches, canonicalized_ | |||
matches_names = [p.name for p in matches] | name) | |||
exact_match = constraint["name"] in matches_names | ||||
if exact_match: | ||||
choices.append( | ||||
matches[matches_names.index(constraint["name"])].pre | ||||
tty_name | ||||
) | ||||
for found_package in matches: | info_string = ( | |||
if len(choices) >= 10: | f"Found <info>{len(matches)}</info> packages matching" | |||
break | f" <c1>{package}</c1>" | |||
if found_package.name.lower() == constraint["name"].lowe | ||||
r(): | ||||
continue | ||||
choices.append(found_package.pretty_name) | ||||
self.line( | ||||
"Found <info>{}</info> packages matching <c1>{}</c1>".fo | ||||
rmat( | ||||
len(matches), package | ||||
) | ||||
) | ) | |||
if len(matches) > 10: | ||||
info_string += "\nShowing the first 10 matches" | ||||
self.line(info_string) | ||||
# Default to an empty value to signal no package was selecte | ||||
d | ||||
choices.append("") | ||||
package = self.choice( | package = self.choice( | |||
"\nEnter package # to add, or the complete package name | "\nEnter package # to add, or the complete package name | |||
if it is not listed", | if it" | |||
" is not listed", | ||||
choices, | choices, | |||
attempts=3, | attempts=3, | |||
default=len(choices) - 1, | ||||
) | ) | |||
if not package: | ||||
self.line("<warning>No package selected</warning>") | ||||
# package selected by user, set constraint name to package n ame | # package selected by user, set constraint name to package n ame | |||
if package is not False: | if package: | |||
constraint["name"] = package | constraint["name"] = package | |||
# no constraint yet, determine the best version automatically | # no constraint yet, determine the best version automatically | |||
if package is not False and "version" not in constraint: | if package and "version" not in constraint: | |||
question = self.create_question( | question = self.create_question( | |||
"Enter the version constraint to require " | "Enter the version constraint to require " | |||
"(or leave blank to use the latest version):" | "(or leave blank to use the latest version):" | |||
) | ) | |||
question.attempts = 3 | question.attempts = 3 | |||
question.validator = lambda x: (x or "").strip() or False | question.validator = lambda x: (x or "").strip() or False | |||
package_constraint = self.ask(question) | package_constraint = self.ask(question) | |||
if package_constraint is None: | if package_constraint is None: | |||
_, package_constraint = self._find_best_version_for_pack age( | _, package_constraint = self._find_best_version_for_pack age( | |||
package | package | |||
) | ) | |||
self.line( | self.line( | |||
"Using version <b>{}</b> for <c1>{}</c1>".format( | f"Using version <b>{package_constraint}</b> for" | |||
package_constraint, package | f" <c1>{package}</c1>" | |||
) | ||||
) | ) | |||
constraint["version"] = package_constraint | constraint["version"] = package_constraint | |||
if package is not False: | if package: | |||
requires.append(constraint) | result.append(constraint) | |||
package = self.ask("\nAdd a package:") | if self.io.is_interactive(): | |||
package = self.ask("\nAdd a package (leave blank to skip):") | ||||
return requires | return result | |||
requires = self._parse_requirements(requires) | ||||
result = [] | result = [] | |||
for requirement in requires: | for requirement in self._parse_requirements(requires): | |||
if "git" in requirement or "url" in requirement or "path" in require ment: | if "git" in requirement or "url" in requirement or "path" in require ment: | |||
result.append(requirement) | result.append(requirement) | |||
continue | continue | |||
elif "version" not in requirement: | elif "version" not in requirement: | |||
# determine the best version automatically | # determine the best version automatically | |||
name, version = self._find_best_version_for_package( | name, version = self._find_best_version_for_package( | |||
requirement["name"], | requirement["name"], | |||
allow_prereleases=allow_prereleases, | allow_prereleases=allow_prereleases, | |||
source=source, | source=source, | |||
) | ) | |||
requirement["version"] = version | requirement["version"] = version | |||
requirement["name"] = name | requirement["name"] = name | |||
self.line( | self.line(f"Using version <b>{version}</b> for <c1>{name}</c1>") | |||
"Using version <b>{}</b> for <c1>{}</c1>".format(version, na | ||||
me) | ||||
) | ||||
else: | else: | |||
# check that the specified version/constraint exists | # check that the specified version/constraint exists | |||
# before we proceed | # before we proceed | |||
name, _ = self._find_best_version_for_package( | name, _ = self._find_best_version_for_package( | |||
requirement["name"], | requirement["name"], | |||
requirement["version"], | requirement["version"], | |||
allow_prereleases=allow_prereleases, | allow_prereleases=allow_prereleases, | |||
source=source, | source=source, | |||
) | ) | |||
requirement["name"] = name | requirement["name"] = name | |||
result.append(requirement) | result.append(requirement) | |||
return result | return result | |||
def _find_best_version_for_package( | def _find_best_version_for_package( | |||
self, name, required_version=None, allow_prereleases=False, source=None | self, | |||
): # type: (...) -> Tuple[str, str] | name: str, | |||
required_version: str | None = None, | ||||
allow_prereleases: bool = False, | ||||
source: str | None = None, | ||||
) -> tuple[str, str]: | ||||
from poetry.version.version_selector import VersionSelector | from poetry.version.version_selector import VersionSelector | |||
selector = VersionSelector(self._get_pool()) | selector = VersionSelector(self._get_pool()) | |||
package = selector.find_best_candidate( | package = selector.find_best_candidate( | |||
name, required_version, allow_prereleases=allow_prereleases, source= source | name, required_version, allow_prereleases=allow_prereleases, source= source | |||
) | ) | |||
if not package: | if not package: | |||
# TODO: find similar | # TODO: find similar | |||
raise ValueError( | raise ValueError(f"Could not find a matching version of package {nam | |||
"Could not find a matching version of package {}".format(name) | e}") | |||
) | ||||
return package.pretty_name, selector.find_recommended_require_version(pa ckage) | return package.pretty_name, selector.find_recommended_require_version(pa ckage) | |||
def _parse_requirements( | def _parse_requirements(self, requirements: list[str]) -> list[dict[str, Any | |||
self, requirements | ]]: | |||
): # type: (List[str]) -> List[Dict[str, str]] | from poetry.core.pyproject.exceptions import PyProjectException | |||
from poetry.puzzle.provider import Provider | ||||
result = [] | ||||
try: | try: | |||
cwd = self.poetry.file.parent | cwd = self.poetry.file.parent | |||
except (PyProjectException, RuntimeError): | except (PyProjectException, RuntimeError): | |||
cwd = Path.cwd() | cwd = Path.cwd() | |||
for requirement in requirements: | return [ | |||
requirement = requirement.strip() | parse_dependency_specification( | |||
extras = [] | requirement=requirement, | |||
extras_m = re.search(r"\[([\w\d,-_ ]+)\]$", requirement) | env=self.env if isinstance(self, EnvCommand) else None, | |||
if extras_m: | cwd=cwd, | |||
extras = [e.strip() for e in extras_m.group(1).split(",")] | ||||
requirement, _ = requirement.split("[") | ||||
url_parsed = urlparse.urlparse(requirement) | ||||
if url_parsed.scheme and url_parsed.netloc: | ||||
# Url | ||||
if url_parsed.scheme in ["git+https", "git+ssh"]: | ||||
from poetry.core.vcs.git import Git | ||||
from poetry.core.vcs.git import ParsedUrl | ||||
parsed = ParsedUrl.parse(requirement) | ||||
url = Git.normalize_url(requirement) | ||||
pair = OrderedDict([("name", parsed.name), ("git", url.url)] | ||||
) | ||||
if parsed.rev: | ||||
pair["rev"] = url.revision | ||||
if extras: | ||||
pair["extras"] = extras | ||||
package = Provider.get_package_from_vcs( | ||||
"git", url.url, rev=pair.get("rev") | ||||
) | ||||
pair["name"] = package.name | ||||
result.append(pair) | ||||
continue | ||||
elif url_parsed.scheme in ["http", "https"]: | ||||
package = Provider.get_package_from_url(requirement) | ||||
pair = OrderedDict( | ||||
[("name", package.name), ("url", package.source_url)] | ||||
) | ||||
if extras: | ||||
pair["extras"] = extras | ||||
result.append(pair) | ||||
continue | ||||
elif (os.path.sep in requirement or "/" in requirement) and cwd.join | ||||
path( | ||||
requirement | ||||
).exists(): | ||||
path = cwd.joinpath(requirement) | ||||
if path.is_file(): | ||||
package = Provider.get_package_from_file(path.resolve()) | ||||
else: | ||||
package = Provider.get_package_from_directory(path) | ||||
result.append( | ||||
OrderedDict( | ||||
[ | ||||
("name", package.name), | ||||
("path", path.relative_to(cwd).as_posix()), | ||||
] | ||||
+ ([("extras", extras)] if extras else []) | ||||
) | ||||
) | ||||
continue | ||||
pair = re.sub( | ||||
"^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirem | ||||
ent | ||||
) | ) | |||
pair = pair.strip() | for requirement in requirements | |||
] | ||||
require = OrderedDict() | ||||
if " " in pair: | ||||
name, version = pair.split(" ", 2) | ||||
extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) | ||||
if extras_m: | ||||
extras = [e.strip() for e in extras_m.group(1).split(",")] | ||||
name, _ = name.split("[") | ||||
require["name"] = name | ||||
if version != "latest": | ||||
require["version"] = version | ||||
else: | ||||
m = re.match( | ||||
r"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.s | ||||
trip() | ||||
) | ||||
if m: | ||||
name, constraint = m.group(1), m.group(2) | ||||
extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) | ||||
if extras_m: | ||||
extras = [e.strip() for e in extras_m.group(1).split("," | ||||
)] | ||||
name, _ = name.split("[") | ||||
require["name"] = name | def _format_requirements(self, requirements: list[dict[str, str]]) -> Requir | |||
require["version"] = constraint | ements: | |||
else: | requires: Requirements = {} | |||
extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair) | ||||
if extras_m: | ||||
extras = [e.strip() for e in extras_m.group(1).split("," | ||||
)] | ||||
pair, _ = pair.split("[") | ||||
require["name"] = pair | ||||
if extras: | ||||
require["extras"] = extras | ||||
result.append(require) | ||||
return result | ||||
def _format_requirements( | ||||
self, requirements | ||||
): # type: (List[Dict[str, str]]) -> Dict[str, Union[str, Dict[str, str]]] | ||||
requires = {} | ||||
for requirement in requirements: | for requirement in requirements: | |||
name = requirement.pop("name") | name = requirement.pop("name") | |||
constraint: str | InlineTable | ||||
if "version" in requirement and len(requirement) == 1: | if "version" in requirement and len(requirement) == 1: | |||
constraint = requirement["version"] | constraint = requirement["version"] | |||
else: | else: | |||
constraint = inline_table() | constraint = inline_table() | |||
constraint.trivia.trail = "\n" | constraint.trivia.trail = "\n" | |||
constraint.update(requirement) | constraint.update(requirement) | |||
requires[name] = constraint | requires[name] = constraint | |||
return requires | return requires | |||
def _validate_author(self, author, default): | def _validate_author(self, author: str, default: str) -> str | None: | |||
from poetry.core.packages.package import AUTHOR_REGEX | from poetry.core.packages.package import AUTHOR_REGEX | |||
author = author or default | author = author or default | |||
if author in ["n", "no"]: | if author in ["n", "no"]: | |||
return | return None | |||
m = AUTHOR_REGEX.match(author) | m = AUTHOR_REGEX.match(author) | |||
if not m: | if not m: | |||
raise ValueError( | raise ValueError( | |||
"Invalid author string. Must be in the format: " | "Invalid author string. Must be in the format: " | |||
"John Smith <john@example.com>" | "John Smith <john@example.com>" | |||
) | ) | |||
return author | return author | |||
def _validate_license(self, license): | @staticmethod | |||
from poetry.core.spdx import license_by_id | def _validate_package(package: str | None) -> str | None: | |||
if package and len(package.split()) > 2: | ||||
if license: | raise ValueError("Invalid package definition.") | |||
license_by_id(license) | ||||
return license | return package | |||
def _get_pool(self): | def _get_pool(self) -> Pool: | |||
from poetry.repositories import Pool | from poetry.repositories import Pool | |||
from poetry.repositories.pypi_repository import PyPiRepository | from poetry.repositories.pypi_repository import PyPiRepository | |||
if isinstance(self, EnvCommand): | if isinstance(self, EnvCommand): | |||
return self.poetry.pool | return self.poetry.pool | |||
if self._pool is None: | if self._pool is None: | |||
self._pool = Pool() | self._pool = Pool() | |||
self._pool.add_repository(PyPiRepository()) | self._pool.add_repository(PyPiRepository()) | |||
End of changes. 71 change blocks. | ||||
270 lines changed or deleted | 192 lines changed or added |