def handle(self) -> int: from pathlib import Path from cleo.io.inputs.string_input import StringInput from cleo.io.io import IO from poetry.factory import Factory from poetry.utils.env import EnvManager plugins = self.argument("plugins") system_env = EnvManager.get_system_env(naive=True) env_dir = Path(os.getenv("POETRY_HOME") or system_env.path) # From this point forward, all the logic will be deferred to # the remove command, by using the global `pyproject.toml` file. application = cast(Application, self.application) remove_command: RemoveCommand = cast(RemoveCommand, application.find("remove")) # We won't go through the event dispatching done by the application # so we need to configure the command manually remove_command.set_poetry(Factory().create_poetry(env_dir)) remove_command.set_env(system_env) application._configure_installer(remove_command, self._io) argv = ["remove"] + plugins if self.option("dry-run"): argv.append("--dry-run") return remove_command.run( IO( StringInput(" ".join(argv)), self._io.output, self._io.error_output, ))
def _update_with_new_method(self, version): from poetry.config.config import Config from poetry.core.packages.dependency import Dependency from poetry.core.packages.project_package import ProjectPackage from poetry.installation.installer import Installer from poetry.packages.locker import NullLocker from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager env = EnvManager.get_system_env(naive=True) installed = InstalledRepository.load(env) root = ProjectPackage("poetry-updater", "0.0.0") root.python_versions = ".".join(str(c) for c in env.version_info[:3]) root.add_dependency(Dependency("poetry", version.text)) installer = Installer( self.io, env, root, NullLocker(self.data_dir.joinpath("poetry.lock"), {}), self.pool, Config(), installed=installed, ) installer.update(True) installer.run()
def handle(self): from poetry.__version__ import __version__ from poetry.core.semver import Version from poetry.utils.env import EnvManager new_update_method = False try: self._check_recommended_installation() except RuntimeError as e: env = EnvManager.get_system_env(naive=True) try: env.path.relative_to(self.data_dir) except ValueError: raise e new_update_method = True version = self.argument("version") if not version: version = ">=" + __version__ repo = self.pool.repositories[0] packages = repo.find_packages( Dependency("poetry", version, allows_prereleases=self.option("preview"))) if not packages: self.line("No release found for the specified version") return packages.sort(key=cmp_to_key(lambda x, y: 0 if x.version == y.version else int(x.version < y.version or -1))) release = None for package in packages: if package.is_prerelease(): if self.option("preview"): release = package break continue release = package break if release is None: self.line("No new release found") return if release.version == Version.parse(__version__): self.line("You are using the latest version") return if new_update_method: return self.update_with_new_method(release.version) self.update(release)
def update(self, release: Package) -> None: from poetry.utils.env import EnvManager version = release.version env = EnvManager.get_system_env(naive=True) # We can't use is_relative_to() since it's only available in Python 3.9+ try: env.path.relative_to(self.data_dir) except ValueError: # Poetry was not installed using the recommended installer from poetry.console.exceptions import PoetrySimpleConsoleException raise PoetrySimpleConsoleException( "Poetry was not installed with the recommended installer, " "so it cannot be updated automatically.") self._update(version) self._make_bin()
def handle(self) -> int: from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.plugin import Plugin from poetry.plugins.plugin_manager import PluginManager from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager from poetry.utils.helpers import canonicalize_name from poetry.utils.helpers import pluralize plugins: dict[str, dict[str, Any]] = defaultdict(lambda: { "package": None, "plugins": [], "application_plugins": [], }) entry_points = ( PluginManager(ApplicationPlugin.group).get_plugin_entry_points() + PluginManager(Plugin.group).get_plugin_entry_points()) system_env = EnvManager.get_system_env(naive=True) installed_repository = InstalledRepository.load(system_env, with_dependencies=True) packages_by_name = { pkg.name: pkg for pkg in installed_repository.packages } for entry_point in entry_points: plugin = entry_point.load() category = "plugins" if issubclass(plugin, ApplicationPlugin): category = "application_plugins" package = packages_by_name[canonicalize_name( entry_point.distro.name)] plugins[package.pretty_name]["package"] = package plugins[package.pretty_name][category].append(entry_point) for name, info in plugins.items(): package = info["package"] description = " " + package.description if package.description else "" self.line("") self.line( f" • <c1>{name}</c1> (<c2>{package.version}</c2>){description}" ) provide_line = " " if info["plugins"]: count = len(info["plugins"]) provide_line += f" <info>{count}</info> plugin{pluralize(count)}" if info["application_plugins"]: if info["plugins"]: provide_line += " and" count = len(info["application_plugins"]) provide_line += ( f" <info>{count}</info> application plugin{pluralize(count)}" ) self.line(provide_line) if package.requires: self.line("") self.line(" <info>Dependencies</info>") for dependency in package.requires: self.line(f" - {dependency.pretty_name}" f" (<c2>{dependency.pretty_constraint}</c2>)") return 0
def handle(self) -> int: from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.plugin_manager import PluginManager from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager from poetry.utils.helpers import canonicalize_name plugins: DefaultDict[str, Dict[str, Union[ "Package", List[str]]]] = defaultdict(lambda: { "package": None, "plugins": [], "application_plugins": [], }) entry_points = ( PluginManager("application.plugin").get_plugin_entry_points() + PluginManager("plugin").get_plugin_entry_points()) system_env = EnvManager.get_system_env(naive=True) installed_repository = InstalledRepository.load(system_env, with_dependencies=True) packages_by_name = { pkg.name: pkg for pkg in installed_repository.packages } for entry_point in entry_points: plugin = entry_point.load() category = "plugins" if issubclass(plugin, ApplicationPlugin): category = "application_plugins" package = packages_by_name[canonicalize_name(entry_point.name)] plugins[package.pretty_name]["package"] = package plugins[package.pretty_name][category].append(entry_point) for name, info in plugins.items(): package = info["package"] self.line("") self.line(" • <c1>{}</c1> (<c2>{}</c2>){}".format( name, package.version, " " + package.description if package.description else "", )) provide_line = " " if info["plugins"]: provide_line += " <info>{}</info> plugin{}".format( len(info["plugins"]), "s" if len(info["plugins"]) > 1 else "") if info["application_plugins"]: if info["plugins"]: provide_line += " and" provide_line += " <info>{}</info> application plugin{}".format( len(info["application_plugins"]), "s" if len(info["application_plugins"]) > 1 else "", ) self.line(provide_line) if package.requires: self.line("") self.line(" <info>Dependencies</info>") for dependency in package.requires: self.line(" - {} (<c2>{}</c2>)".format( dependency.pretty_name, dependency.pretty_constraint)) return 0
def _system_project_handle(self) -> int: from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.plugin import Plugin from poetry.plugins.plugin_manager import PluginManager from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager from poetry.utils.helpers import canonicalize_name from poetry.utils.helpers import pluralize plugins: dict[str, PluginPackage] = {} system_env = EnvManager.get_system_env(naive=True) entry_points = PluginManager( ApplicationPlugin.group).get_plugin_entry_points( env=system_env) + PluginManager( Plugin.group).get_plugin_entry_points(env=system_env) installed_repository = InstalledRepository.load(system_env, with_dependencies=True) packages_by_name: dict[str, Package] = { pkg.name: pkg for pkg in installed_repository.packages } for entry_point in entry_points: plugin = entry_point.load() assert entry_point.distro is not None package = packages_by_name[canonicalize_name( entry_point.distro.name)] name = package.pretty_name info = plugins.get(name) or PluginPackage(package=package) if issubclass(plugin, ApplicationPlugin): info.application_plugins.append(entry_point) else: info.plugins.append(entry_point) plugins[name] = info for name, info in plugins.items(): package = info.package description = " " + package.description if package.description else "" self.line("") self.line( f" • <c1>{name}</c1> (<c2>{package.version}</c2>){description}" ) provide_line = " " if info.plugins: count = len(info.plugins) provide_line += f" <info>{count}</info> plugin{pluralize(count)}" if info.application_plugins: if info.plugins: provide_line += " and" count = len(info.application_plugins) provide_line += ( f" <info>{count}</info> application plugin{pluralize(count)}" ) self.line(provide_line) if package.requires: self.line("") self.line(" <info>Dependencies</info>") for dependency in package.requires: self.line(f" - {dependency.pretty_name}" f" (<c2>{dependency.pretty_constraint}</c2>)") return 0
def handle(self) -> int: from pathlib import Path import tomlkit from cleo.io.inputs.string_input import StringInput from cleo.io.io import IO from poetry.core.pyproject.toml import PyProjectTOML from poetry.core.semver.helpers import parse_constraint from poetry.factory import Factory from poetry.packages.project_package import ProjectPackage from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager plugins = self.argument("plugins") # Plugins should be installed in the system env to be globally available system_env = EnvManager.get_system_env(naive=True) env_dir = Path(os.getenv("POETRY_HOME") or system_env.path) # We check for the plugins existence first. if env_dir.joinpath("pyproject.toml").exists(): pyproject = tomlkit.loads( env_dir.joinpath("pyproject.toml").read_text(encoding="utf-8")) poetry_content = pyproject["tool"]["poetry"] existing_packages = self.get_existing_packages_from_input( plugins, poetry_content, "dependencies") if existing_packages: self.notify_about_existing_packages(existing_packages) plugins = [ plugin for plugin in plugins if plugin not in existing_packages ] if not plugins: return 0 plugins = self._determine_requirements(plugins) # We retrieve the packages installed in the system environment. # We assume that this environment will be a self contained virtual environment # built by the official installer or by pipx. # If not, it might lead to side effects since other installed packages # might not be required by Poetry but still taken into account when resolving dependencies. installed_repository = InstalledRepository.load(system_env, with_dependencies=True) root_package = None for package in installed_repository.packages: if package.name == "poetry": root_package = ProjectPackage(package.name, package.version) for dependency in package.requires: root_package.add_dependency(dependency) break root_package.python_versions = ".".join( str(v) for v in system_env.version_info[:3]) # We create a `pyproject.toml` file based on all the information # we have about the current environment. if not env_dir.joinpath("pyproject.toml").exists(): Factory.create_pyproject_from_package(root_package, env_dir) # We add the plugins to the dependencies section of the previously # created `pyproject.toml` file pyproject = PyProjectTOML(env_dir.joinpath("pyproject.toml")) poetry_content = pyproject.poetry_config poetry_dependency_section = poetry_content["dependencies"] plugin_names = [] for plugin in plugins: if "version" in plugin: # Validate version constraint parse_constraint(plugin["version"]) constraint = tomlkit.inline_table() for name, value in plugin.items(): if name == "name": continue constraint[name] = value if len(constraint) == 1 and "version" in constraint: constraint = constraint["version"] poetry_dependency_section[plugin["name"]] = constraint plugin_names.append(plugin["name"]) pyproject.save() # From this point forward, all the logic will be deferred to # the update command, by using the previously created `pyproject.toml` # file. application = cast(Application, self.application) update_command: UpdateCommand = cast(UpdateCommand, application.find("update")) # We won't go through the event dispatching done by the application # so we need to configure the command manually update_command.set_poetry(Factory().create_poetry(env_dir)) update_command.set_env(system_env) application._configure_installer(update_command, self._io) argv = ["update"] + plugin_names if self.option("dry-run"): argv.append("--dry-run") return update_command.run( IO( StringInput(" ".join(argv)), self._io.output, self._io.error_output, ))
def reset_env(self) -> None: self._env = EnvManager.get_system_env(naive=True)