summaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__init__.py13
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__main__.py65
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__init__.cpython-312.pycbin0 -> 382 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__main__.cpython-312.pycbin0 -> 2704 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_implementation.cpython-312.pycbin0 -> 9656 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_lint_dependency_groups.cpython-312.pycbin0 -> 2869 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_pip_wrapper.cpython-312.pycbin0 -> 3436 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_toml_compat.cpython-312.pycbin0 -> 483 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_implementation.py209
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py59
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py62
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_toml_compat.py9
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/py.typed0
13 files changed, 417 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__init__.py
new file mode 100644
index 0000000..9fec202
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__init__.py
@@ -0,0 +1,13 @@
+from ._implementation import (
+ CyclicDependencyError,
+ DependencyGroupInclude,
+ DependencyGroupResolver,
+ resolve,
+)
+
+__all__ = (
+ "CyclicDependencyError",
+ "DependencyGroupInclude",
+ "DependencyGroupResolver",
+ "resolve",
+)
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__main__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__main__.py
new file mode 100644
index 0000000..48ebb0d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__main__.py
@@ -0,0 +1,65 @@
+import argparse
+import sys
+
+from ._implementation import resolve
+from ._toml_compat import tomllib
+
+
+def main() -> None:
+ if tomllib is None:
+ print(
+ "Usage error: dependency-groups CLI requires tomli or Python 3.11+",
+ file=sys.stderr,
+ )
+ raise SystemExit(2)
+
+ parser = argparse.ArgumentParser(
+ description=(
+ "A dependency-groups CLI. Prints out a resolved group, newline-delimited."
+ )
+ )
+ parser.add_argument(
+ "GROUP_NAME", nargs="*", help="The dependency group(s) to resolve."
+ )
+ parser.add_argument(
+ "-f",
+ "--pyproject-file",
+ default="pyproject.toml",
+ help="The pyproject.toml file. Defaults to trying in the current directory.",
+ )
+ parser.add_argument(
+ "-o",
+ "--output",
+ help="An output file. Defaults to stdout.",
+ )
+ parser.add_argument(
+ "-l",
+ "--list",
+ action="store_true",
+ help="List the available dependency groups",
+ )
+ args = parser.parse_args()
+
+ with open(args.pyproject_file, "rb") as fp:
+ pyproject = tomllib.load(fp)
+
+ dependency_groups_raw = pyproject.get("dependency-groups", {})
+
+ if args.list:
+ print(*dependency_groups_raw.keys())
+ return
+ if not args.GROUP_NAME:
+ print("A GROUP_NAME is required", file=sys.stderr)
+ raise SystemExit(3)
+
+ content = "\n".join(resolve(dependency_groups_raw, *args.GROUP_NAME))
+
+ if args.output is None or args.output == "-":
+ print(content)
+ else:
+ with open(args.output, "w", encoding="utf-8") as fp:
+ print(content, file=fp)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..95091da
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__main__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..dbe877a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/__main__.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_implementation.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_implementation.cpython-312.pyc
new file mode 100644
index 0000000..1c31334
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_implementation.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_lint_dependency_groups.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_lint_dependency_groups.cpython-312.pyc
new file mode 100644
index 0000000..b54783e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_lint_dependency_groups.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_pip_wrapper.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_pip_wrapper.cpython-312.pyc
new file mode 100644
index 0000000..f3a8897
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_pip_wrapper.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_toml_compat.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_toml_compat.cpython-312.pyc
new file mode 100644
index 0000000..528d177
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/__pycache__/_toml_compat.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_implementation.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_implementation.py
new file mode 100644
index 0000000..64e314a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_implementation.py
@@ -0,0 +1,209 @@
+from __future__ import annotations
+
+import dataclasses
+import re
+from collections.abc import Mapping
+
+from pip._vendor.packaging.requirements import Requirement
+
+
+def _normalize_name(name: str) -> str:
+ return re.sub(r"[-_.]+", "-", name).lower()
+
+
+def _normalize_group_names(
+ dependency_groups: Mapping[str, str | Mapping[str, str]],
+) -> Mapping[str, str | Mapping[str, str]]:
+ original_names: dict[str, list[str]] = {}
+ normalized_groups = {}
+
+ for group_name, value in dependency_groups.items():
+ normed_group_name = _normalize_name(group_name)
+ original_names.setdefault(normed_group_name, []).append(group_name)
+ normalized_groups[normed_group_name] = value
+
+ errors = []
+ for normed_name, names in original_names.items():
+ if len(names) > 1:
+ errors.append(f"{normed_name} ({', '.join(names)})")
+ if errors:
+ raise ValueError(f"Duplicate dependency group names: {', '.join(errors)}")
+
+ return normalized_groups
+
+
+@dataclasses.dataclass
+class DependencyGroupInclude:
+ include_group: str
+
+
+class CyclicDependencyError(ValueError):
+ """
+ An error representing the detection of a cycle.
+ """
+
+ def __init__(self, requested_group: str, group: str, include_group: str) -> None:
+ self.requested_group = requested_group
+ self.group = group
+ self.include_group = include_group
+
+ if include_group == group:
+ reason = f"{group} includes itself"
+ else:
+ reason = f"{include_group} -> {group}, {group} -> {include_group}"
+ super().__init__(
+ "Cyclic dependency group include while resolving "
+ f"{requested_group}: {reason}"
+ )
+
+
+class DependencyGroupResolver:
+ """
+ A resolver for Dependency Group data.
+
+ This class handles caching, name normalization, cycle detection, and other
+ parsing requirements. There are only two public methods for exploring the data:
+ ``lookup()`` and ``resolve()``.
+
+ :param dependency_groups: A mapping, as provided via pyproject
+ ``[dependency-groups]``.
+ """
+
+ def __init__(
+ self,
+ dependency_groups: Mapping[str, str | Mapping[str, str]],
+ ) -> None:
+ if not isinstance(dependency_groups, Mapping):
+ raise TypeError("Dependency Groups table is not a mapping")
+ self.dependency_groups = _normalize_group_names(dependency_groups)
+ # a map of group names to parsed data
+ self._parsed_groups: dict[
+ str, tuple[Requirement | DependencyGroupInclude, ...]
+ ] = {}
+ # a map of group names to their ancestors, used for cycle detection
+ self._include_graph_ancestors: dict[str, tuple[str, ...]] = {}
+ # a cache of completed resolutions to Requirement lists
+ self._resolve_cache: dict[str, tuple[Requirement, ...]] = {}
+
+ def lookup(self, group: str) -> tuple[Requirement | DependencyGroupInclude, ...]:
+ """
+ Lookup a group name, returning the parsed dependency data for that group.
+ This will not resolve includes.
+
+ :param group: the name of the group to lookup
+
+ :raises ValueError: if the data does not appear to be valid dependency group
+ data
+ :raises TypeError: if the data is not a string
+ :raises LookupError: if group name is absent
+ :raises packaging.requirements.InvalidRequirement: if a specifier is not valid
+ """
+ if not isinstance(group, str):
+ raise TypeError("Dependency group name is not a str")
+ group = _normalize_name(group)
+ return self._parse_group(group)
+
+ def resolve(self, group: str) -> tuple[Requirement, ...]:
+ """
+ Resolve a dependency group to a list of requirements.
+
+ :param group: the name of the group to resolve
+
+ :raises TypeError: if the inputs appear to be the wrong types
+ :raises ValueError: if the data does not appear to be valid dependency group
+ data
+ :raises LookupError: if group name is absent
+ :raises packaging.requirements.InvalidRequirement: if a specifier is not valid
+ """
+ if not isinstance(group, str):
+ raise TypeError("Dependency group name is not a str")
+ group = _normalize_name(group)
+ return self._resolve(group, group)
+
+ def _parse_group(
+ self, group: str
+ ) -> tuple[Requirement | DependencyGroupInclude, ...]:
+ # short circuit -- never do the work twice
+ if group in self._parsed_groups:
+ return self._parsed_groups[group]
+
+ if group not in self.dependency_groups:
+ raise LookupError(f"Dependency group '{group}' not found")
+
+ raw_group = self.dependency_groups[group]
+ if not isinstance(raw_group, list):
+ raise TypeError(f"Dependency group '{group}' is not a list")
+
+ elements: list[Requirement | DependencyGroupInclude] = []
+ for item in raw_group:
+ if isinstance(item, str):
+ # packaging.requirements.Requirement parsing ensures that this is a
+ # valid PEP 508 Dependency Specifier
+ # raises InvalidRequirement on failure
+ elements.append(Requirement(item))
+ elif isinstance(item, dict):
+ if tuple(item.keys()) != ("include-group",):
+ raise ValueError(f"Invalid dependency group item: {item}")
+
+ include_group = next(iter(item.values()))
+ elements.append(DependencyGroupInclude(include_group=include_group))
+ else:
+ raise ValueError(f"Invalid dependency group item: {item}")
+
+ self._parsed_groups[group] = tuple(elements)
+ return self._parsed_groups[group]
+
+ def _resolve(self, group: str, requested_group: str) -> tuple[Requirement, ...]:
+ """
+ This is a helper for cached resolution to strings.
+
+ :param group: The name of the group to resolve.
+ :param requested_group: The group which was used in the original, user-facing
+ request.
+ """
+ if group in self._resolve_cache:
+ return self._resolve_cache[group]
+
+ parsed = self._parse_group(group)
+
+ resolved_group = []
+ for item in parsed:
+ if isinstance(item, Requirement):
+ resolved_group.append(item)
+ elif isinstance(item, DependencyGroupInclude):
+ include_group = _normalize_name(item.include_group)
+ if include_group in self._include_graph_ancestors.get(group, ()):
+ raise CyclicDependencyError(
+ requested_group, group, item.include_group
+ )
+ self._include_graph_ancestors[include_group] = (
+ *self._include_graph_ancestors.get(group, ()),
+ group,
+ )
+ resolved_group.extend(self._resolve(include_group, requested_group))
+ else: # unreachable
+ raise NotImplementedError(
+ f"Invalid dependency group item after parse: {item}"
+ )
+
+ self._resolve_cache[group] = tuple(resolved_group)
+ return self._resolve_cache[group]
+
+
+def resolve(
+ dependency_groups: Mapping[str, str | Mapping[str, str]], /, *groups: str
+) -> tuple[str, ...]:
+ """
+ Resolve a dependency group to a tuple of requirements, as strings.
+
+ :param dependency_groups: the parsed contents of the ``[dependency-groups]`` table
+ from ``pyproject.toml``
+ :param groups: the name of the group(s) to resolve
+
+ :raises TypeError: if the inputs appear to be the wrong types
+ :raises ValueError: if the data does not appear to be valid dependency group data
+ :raises LookupError: if group name is absent
+ :raises packaging.requirements.InvalidRequirement: if a specifier is not valid
+ """
+ resolver = DependencyGroupResolver(dependency_groups)
+ return tuple(str(r) for group in groups for r in resolver.resolve(group))
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py
new file mode 100644
index 0000000..09454bd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py
@@ -0,0 +1,59 @@
+from __future__ import annotations
+
+import argparse
+import sys
+
+from ._implementation import DependencyGroupResolver
+from ._toml_compat import tomllib
+
+
+def main(*, argv: list[str] | None = None) -> None:
+ if tomllib is None:
+ print(
+ "Usage error: dependency-groups CLI requires tomli or Python 3.11+",
+ file=sys.stderr,
+ )
+ raise SystemExit(2)
+
+ parser = argparse.ArgumentParser(
+ description=(
+ "Lint Dependency Groups for validity. "
+ "This will eagerly load and check all of your Dependency Groups."
+ )
+ )
+ parser.add_argument(
+ "-f",
+ "--pyproject-file",
+ default="pyproject.toml",
+ help="The pyproject.toml file. Defaults to trying in the current directory.",
+ )
+ args = parser.parse_args(argv if argv is not None else sys.argv[1:])
+
+ with open(args.pyproject_file, "rb") as fp:
+ pyproject = tomllib.load(fp)
+ dependency_groups_raw = pyproject.get("dependency-groups", {})
+
+ errors: list[str] = []
+ try:
+ resolver = DependencyGroupResolver(dependency_groups_raw)
+ except (ValueError, TypeError) as e:
+ errors.append(f"{type(e).__name__}: {e}")
+ else:
+ for groupname in resolver.dependency_groups:
+ try:
+ resolver.resolve(groupname)
+ except (LookupError, ValueError, TypeError) as e:
+ errors.append(f"{type(e).__name__}: {e}")
+
+ if errors:
+ print("errors encountered while examining dependency groups:")
+ for msg in errors:
+ print(f" {msg}")
+ sys.exit(1)
+ else:
+ print("ok")
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py
new file mode 100644
index 0000000..f86d896
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py
@@ -0,0 +1,62 @@
+from __future__ import annotations
+
+import argparse
+import subprocess
+import sys
+
+from ._implementation import DependencyGroupResolver
+from ._toml_compat import tomllib
+
+
+def _invoke_pip(deps: list[str]) -> None:
+ subprocess.check_call([sys.executable, "-m", "pip", "install", *deps])
+
+
+def main(*, argv: list[str] | None = None) -> None:
+ if tomllib is None:
+ print(
+ "Usage error: dependency-groups CLI requires tomli or Python 3.11+",
+ file=sys.stderr,
+ )
+ raise SystemExit(2)
+
+ parser = argparse.ArgumentParser(description="Install Dependency Groups.")
+ parser.add_argument(
+ "DEPENDENCY_GROUP", nargs="+", help="The dependency groups to install."
+ )
+ parser.add_argument(
+ "-f",
+ "--pyproject-file",
+ default="pyproject.toml",
+ help="The pyproject.toml file. Defaults to trying in the current directory.",
+ )
+ args = parser.parse_args(argv if argv is not None else sys.argv[1:])
+
+ with open(args.pyproject_file, "rb") as fp:
+ pyproject = tomllib.load(fp)
+ dependency_groups_raw = pyproject.get("dependency-groups", {})
+
+ errors: list[str] = []
+ resolved: list[str] = []
+ try:
+ resolver = DependencyGroupResolver(dependency_groups_raw)
+ except (ValueError, TypeError) as e:
+ errors.append(f"{type(e).__name__}: {e}")
+ else:
+ for groupname in args.DEPENDENCY_GROUP:
+ try:
+ resolved.extend(str(r) for r in resolver.resolve(groupname))
+ except (LookupError, ValueError, TypeError) as e:
+ errors.append(f"{type(e).__name__}: {e}")
+
+ if errors:
+ print("errors encountered while examining dependency groups:")
+ for msg in errors:
+ print(f" {msg}")
+ sys.exit(1)
+
+ _invoke_pip(resolved)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_toml_compat.py b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_toml_compat.py
new file mode 100644
index 0000000..8d6f921
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/_toml_compat.py
@@ -0,0 +1,9 @@
+try:
+ import tomllib
+except ImportError:
+ try:
+ from pip._vendor import tomli as tomllib # type: ignore[no-redef, unused-ignore]
+ except ModuleNotFoundError: # pragma: no cover
+ tomllib = None # type: ignore[assignment, unused-ignore]
+
+__all__ = ("tomllib",)
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/py.typed b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/py.typed
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/dependency_groups/py.typed