Source code for meta_package_manager.managers.composer

# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

from __future__ import annotations

import json
import re
from typing import Iterator

from extra_platforms import ALL_PLATFORMS

from meta_package_manager.base import Package, PackageManager
from meta_package_manager.capabilities import (
    search_capabilities,
    version_not_implemented,
)


[docs] class Composer(PackageManager): name = "PHP's Composer" homepage_url = "https://getcomposer.org" platforms = ALL_PLATFORMS requirement = "1.4.0" pre_args = ("global",) version_regex = r"Composer\s+version\s+(?P<version>\S+)" """ .. code-block:: shell-session ► composer --version Composer version 2.1.8 2021-09-15 13:55:14 """ @property def installed(self) -> Iterator[Package]: """Fetch installed packages. .. code-block:: shell-session ► composer global show --format=json | jq { "installed": [ { "name": "carbondate/carbon", "version": "1.33.0", "description": "A simple API extension for DateTime." }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", "description": "Guzzle is a PHP HTTP client library" }, { "name": "guzzlehttp/promises", "version": "v1.3.1", "description": "Guzzle promises library" }, { "name": "guzzlehttp/psr7", "version": "1.4.2", "description": "PSR-7 message (...) methods" }, (...) """ output = self.run_cli("show", "--format=json") if output: package_list = json.loads(output) for package in package_list["installed"]: package_id = package["name"] yield self.package(id=package_id, installed_version=package["version"]) @property def outdated(self) -> Iterator[Package]: """Fetch outdated packages. .. code-block:: shell-session ► composer global outdated --format=json { "installed": [ { "name": "illuminate/contracts", "version": "v5.7.2", "latest": "v5.7.3", "latest-status": "semver-safe-update", "description": "The Illuminate Contracts package." }, { "name": "illuminate/support", "version": "v5.7.2", "latest": "v5.7.3", "latest-status": "semver-safe-update", "description": "The Illuminate Support package." } ] } """ output = self.run_cli("outdated", "--format=json") if output: package_list = json.loads(output) for package in package_list["installed"]: package_id = package["name"] yield self.package( id=package_id, installed_version=package["version"], latest_version=package["latest"], )
[docs] @search_capabilities(exact_support=False) def search(self, query: str, extended: bool, exact: bool) -> Iterator[Package]: """Fetch matching packages. .. caution:: Search does not supports exact matching. .. code-block:: shell-session ► composer global search symfony symfony/symfony The Symfony PHP framework symfony/yaml Symfony Yaml Component symfony/var-dumper Symfony (...) dumping PHP variables symfony/translation Symfony Translation Component symfony/routing Symfony Routing Component symfony/process Symfony Process Component symfony/polyfill-php70 Symfony (...) features to lower PHP versions symfony/polyfill-mbstring Symfony (...) Mbstring extension symfony/polyfill-ctype Symfony polyfill for ctype functions symfony/http-kernel Symfony HttpKernel Component symfony/http-foundation Symfony HttpFoundation Component symfony/finder Symfony Finder Component symfony/event-dispatcher Symfony EventDispatcher Component symfony/debug Symfony Debug Component symfony/css-selector Symfony CssSelector Component .. code-block:: shell-session ► composer global search --only-name python hiqdev/hidev-python aanro/pythondocx laravel-admin-ext/python-editor pythonphp/pythonphp blyxxyz/python-server nim-development/python-domotics rakshitbharat/pythoninphp tequilarapido/python-bridge .. code-block:: shell-session ► search global --only-name pythonphp/pythonphp pythonphp/pythonphp """ search_args = [] if not extended: search_args.append("--only-name") output = self.run_cli("search", search_args, query) regexp = re.compile( r""" ^(?P<package_id>\S+\/\S+) (?P<description> .*)? """, re.MULTILINE | re.VERBOSE, ) for package_id, description in regexp.findall(output): yield self.package(id=package_id, description=description)
@version_not_implemented def install(self, package_id: str, version: str | None = None) -> str: """Install one package. .. code-block:: shell-session ► composer global install illuminate/contracts """ return self.run_cli("install", package_id)
[docs] def upgrade_all_cli(self) -> tuple[str, ...]: """Generates the CLI to upgrade all packages (default) or only the one provided as parameter. .. code-block:: shell-session ► composer global update """ return self.build_cli("update")
@version_not_implemented def upgrade_one_cli( self, package_id: str, version: str | None = None, ) -> tuple[str, ...]: """Generates the CLI to upgrade all packages (default) or only the one provided as parameter. .. code-block:: shell-session ► composer global update illuminate/contracts """ return self.build_cli("update", package_id)
[docs] def cleanup(self) -> None: """Removes things we don't need anymore. See: https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-cc .. code-block:: shell-session ► composer global clear-cache """ self.run_cli("clear-cache")