def _install_directory(self, operation: Install | Update) -> int: from poetry.factory import Factory package = operation.package operation_message = self.get_operation_message(operation) message = ( f" <fg=blue;options=bold>•</> {operation_message}:" " <info>Building...</info>" ) self._write(operation, message) assert package.source_url is not None if package.root_dir: req = package.root_dir / package.source_url else: req = Path(package.source_url).resolve(strict=False) pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): # Even if there is a build system specified # some versions of pip (< 19.0.0) don't understand it # so we need to check the version of pip to know # if we can rely on the build system legacy_pip = ( self._env.pip_version < self._env.pip_version.__class__.from_parts(19, 0, 0) ) package_poetry = Factory().create_poetry(pyproject.file.path.parent) builder: Builder if package.develop and not package_poetry.package.build_script: from poetry.masonry.builders.editable import EditableBuilder # This is a Poetry package in editable mode # we can use the EditableBuilder without going through pip # to install it, unless it has a build script. builder = EditableBuilder(package_poetry, self._env, NullIO()) builder.build() return 0 elif legacy_pip or package_poetry.package.build_script: from poetry.core.masonry.builders.sdist import SdistBuilder # We need to rely on creating a temporary setup.py # file since the version of pip does not support # build-systems # We also need it for non-PEP-517 packages builder = SdistBuilder(package_poetry) with builder.setup_py(): if package.develop: return self.pip_install(req, upgrade=True, editable=True) return self.pip_install(req, upgrade=True) if package.develop: return self.pip_install(req, upgrade=True, editable=True) return self.pip_install(req, upgrade=True)
def install_directory(self, package: "Package") -> Union[str, int]: from cleo.io.null_io import NullIO from poetry.factory import Factory req: Path if package.root_dir: req = (package.root_dir / package.source_url).as_posix() else: req = Path(package.source_url).resolve(strict=False) pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): # Even if there is a build system specified # some versions of pip (< 19.0.0) don't understand it # so we need to check the version of pip to know # if we can rely on the build system legacy_pip = self._env.pip_version < self._env.pip_version.__class__( 19, 0, 0) package_poetry = Factory().create_poetry( pyproject.file.path.parent) if package.develop and not package_poetry.package.build_script: from poetry.masonry.builders.editable import EditableBuilder # This is a Poetry package in editable mode # we can use the EditableBuilder without going through pip # to install it, unless it has a build script. builder = EditableBuilder(package_poetry, self._env, NullIO()) builder.build() return 0 elif legacy_pip or package_poetry.package.build_script: from poetry.core.masonry.builders.sdist import SdistBuilder # We need to rely on creating a temporary setup.py # file since the version of pip does not support # build-systems # We also need it for non-PEP-517 packages builder = SdistBuilder(package_poetry) with builder.setup_py(): if package.develop: return pip_editable_install(directory=req, environment=self._env) return pip_install(path=req, environment=self._env, deps=False, upgrade=True) if package.develop: return pip_editable_install(directory=req, environment=self._env) return pip_install(path=req, environment=self._env, deps=False, upgrade=True)
def test_pyproject_toml_poetry_config( pyproject_toml: Path, poetry_section: str ) -> None: pyproject = PyProjectTOML(pyproject_toml) doc: dict[str, Any] = TOMLFile(pyproject_toml.as_posix()).read() config = doc["tool"]["poetry"] assert pyproject.is_poetry_project() assert pyproject.poetry_config == config
def install_directory(self, package): from poetry.factory import Factory from poetry.io.null_io import NullIO if package.root_dir: req = (package.root_dir / package.source_url).as_posix() else: req = os.path.realpath(package.source_url) args = ["install", "--no-deps", "-U"] pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): # Even if there is a build system specified # some versions of pip (< 19.0.0) don't understand it # so we need to check the version of pip to know # if we can rely on the build system legacy_pip = self._env.pip_version < self._env.pip_version.__class__( 19, 0, 0) package_poetry = Factory().create_poetry( pyproject.file.path.parent) if package.develop and not package_poetry.package.build_script: from poetry.masonry.builders.editable import EditableBuilder # This is a Poetry package in editable mode # we can use the EditableBuilder without going through pip # to install it, unless it has a build script. builder = EditableBuilder(package_poetry, self._env, NullIO()) builder.build() return 0 elif legacy_pip or package_poetry.package.build_script: from poetry.core.masonry.builders.sdist import SdistBuilder # We need to rely on creating a temporary setup.py # file since the version of pip does not support # build-systems # We also need it for non-PEP-517 packages builder = SdistBuilder(package_poetry) with builder.setup_py(): if package.develop: args.append("-e") args.append(req) return self.run_pip(*args) if package.develop: args.append("-e") args.append(req) return self.run(*args)
def test_pyproject_toml_no_poetry_config(pyproject_toml): pyproject = PyProjectTOML(pyproject_toml) assert not pyproject.is_poetry_project() with pytest.raises(PyProjectException) as excval: _ = pyproject.poetry_config assert "[tool.poetry] section not found in {}".format( pyproject_toml.as_posix()) in str(excval.value)
def test_pyproject_toml_no_poetry_config(pyproject_toml: Path) -> None: pyproject = PyProjectTOML(pyproject_toml) assert not pyproject.is_poetry_project() with pytest.raises(PyProjectException) as excval: _ = pyproject.poetry_config assert f"[tool.poetry] section not found in {pyproject_toml.as_posix()}" in str( excval.value )
def handle(self) -> int: from pathlib import Path from poetry.core.vcs.git import GitConfig from poetry.layouts import layout from poetry.utils.env import SystemEnv pyproject = PyProjectTOML(Path.cwd() / "pyproject.toml") if pyproject.file.exists(): if pyproject.is_poetry_project(): self.line( "<error>A pyproject.toml file with a poetry section already exists.</error>" ) return 1 if pyproject.data.get("build-system"): self.line( "<error>A pyproject.toml file with a defined build-system already exists.</error>" ) return 1 vcs_config = GitConfig() self.line("") self.line( "This command will guide you through creating your <info>pyproject.toml</> config." ) self.line("") name = self.option("name") if not name: name = Path.cwd().name.lower() question = self.create_question( "Package name [<comment>{}</comment>]: ".format(name), default=name ) name = self.ask(question) version = "0.1.0" question = self.create_question( "Version [<comment>{}</comment>]: ".format(version), default=version ) version = self.ask(question) description = self.option("description") or "" question = self.create_question( "Description [<comment>{}</comment>]: ".format(description), default=description, ) description = self.ask(question) author = self.option("author") if not author and vcs_config and vcs_config.get("user.name"): author = vcs_config["user.name"] author_email = vcs_config.get("user.email") if author_email: author += " <{}>".format(author_email) question = self.create_question( "Author [<comment>{}</comment>, n to skip]: ".format(author), default=author ) question.set_validator(lambda v: self._validate_author(v, author)) author = self.ask(question) if not author: authors = [] else: authors = [author] license = self.option("license") or "" question = self.create_question( "License [<comment>{}</comment>]: ".format(license), default=license ) question.set_validator(self._validate_license) license = self.ask(question) python = self.option("python") if not python: current_env = SystemEnv(Path(sys.executable)) default_python = "^{}".format( ".".join(str(v) for v in current_env.version_info[:2]) ) question = self.create_question( "Compatible Python versions [<comment>{}</comment>]: ".format( default_python ), default=default_python, ) python = self.ask(question) self.line("") requirements = {} if self.option("dependency"): requirements = self._format_requirements( self._determine_requirements(self.option("dependency")) ) question = "Would you like to define your main dependencies interactively?" help_message = ( "You can specify a package in the following forms:\n" " - A single name (<b>requests</b>)\n" " - A name and a constraint (<b>requests@^2.23.0</b>)\n" " - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)\n" " - A git url with a revision (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)\n" " - A file path (<b>../my-package/my-package.whl</b>)\n" " - A directory (<b>../my-package/</b>)\n" " - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)\n" ) help_displayed = False if self.confirm(question, True): self.line(help_message) help_displayed = True requirements.update( self._format_requirements(self._determine_requirements([])) ) self.line("") dev_requirements = {} if self.option("dev-dependency"): dev_requirements = self._format_requirements( self._determine_requirements(self.option("dev-dependency")) ) question = ( "Would you like to define your development dependencies interactively?" ) if self.confirm(question, True): if not help_displayed: self.line(help_message) dev_requirements.update( self._format_requirements(self._determine_requirements([])) ) self.line("") layout_ = layout("standard")( name, version, description=description, author=authors[0] if authors else None, license=license, python=python, dependencies=requirements, dev_dependencies=dev_requirements, ) content = layout_.generate_poetry_content(original=pyproject) if self.io.is_interactive(): self.line("<info>Generated file</info>") self.line("") self.line(content) self.line("") if not self.confirm("Do you confirm generation?", True): self.line("<error>Command aborted</error>") return 1 with (Path.cwd() / "pyproject.toml").open("w", encoding="utf-8") as f: f.write(content)
def _install_directory(self, operation: Union[Install, Update]) -> int: from poetry.factory import Factory package = operation.package operation_message = self.get_operation_message(operation) message = ( " <fg=blue;options=bold>•</> {message}: <info>Building...</info>". format(message=operation_message, )) self._write(operation, message) if package.root_dir: req = os.path.join(str(package.root_dir), package.source_url) else: req = os.path.realpath(package.source_url) args = ["install", "--no-deps", "-U"] pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml")) if pyproject.is_poetry_project(): # Even if there is a build system specified # some versions of pip (< 19.0.0) don't understand it # so we need to check the version of pip to know # if we can rely on the build system legacy_pip = self._env.pip_version < self._env.pip_version.__class__( 19, 0, 0) package_poetry = Factory().create_poetry( pyproject.file.path.parent) if package.develop and not package_poetry.package.build_script: from poetry.masonry.builders.editable import EditableBuilder # This is a Poetry package in editable mode # we can use the EditableBuilder without going through pip # to install it, unless it has a build script. builder = EditableBuilder(package_poetry, self._env, NullIO()) builder.build() return 0 elif legacy_pip or package_poetry.package.build_script: from poetry.core.masonry.builders.sdist import SdistBuilder # We need to rely on creating a temporary setup.py # file since the version of pip does not support # build-systems # We also need it for non-PEP-517 packages builder = SdistBuilder(package_poetry) with builder.setup_py(): if package.develop: args.append("-e") args.append(req) return self.run_pip(*args) if package.develop: args.append("-e") args.append(req) return self.run_pip(*args)
def test_pyproject_toml_poetry_config(pyproject_toml, poetry_section): pyproject = PyProjectTOML(pyproject_toml) config = TOMLFile(pyproject_toml.as_posix()).read()["tool"]["poetry"] assert pyproject.is_poetry_project() assert pyproject.poetry_config == config