diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py index 44a88ca3a17..b17a6d7e404 100644 --- a/src/poetry/packages/locker.py +++ b/src/poetry/packages/locker.py @@ -36,9 +36,9 @@ if TYPE_CHECKING: + from poetry.core.version.markers import BaseMarker from tomlkit.toml_document import TOMLDocument - from poetry.core.version.markers import BaseMarker from poetry.repositories import Repository logger = logging.getLogger(__name__) @@ -240,6 +240,7 @@ def __walk_dependencies( cls, dependencies: List[Dependency], packages_by_name: Dict[str, List[Package]], + extras: Union[bool, Sequence[str]] = False, ) -> Dict[Package, Dependency]: nested_dependencies: Dict[Package, Dependency] = {} @@ -255,10 +256,7 @@ def __walk_dependencies( ) if not locked_package: - # Should normally be able to satisfy all requirements, but this case is - # permissible eg if we encounter a dev dependency when walking the - # non-dev dependencies. - continue + raise RuntimeError(f"Dependency walk failed at {requirement}") # create dependency from locked package to retain dependency metadata # if this is not done, we can end-up with incorrect nested dependencies @@ -270,6 +268,16 @@ def __walk_dependencies( requirement.set_constraint(constraint) for require in locked_package.requires: + # Ignore unwanted extras. + if require.is_optional(): + keep = ( + extras + if isinstance(extras, bool) + else any(extra in require.in_extras for extra in extras) + ) + if not keep: + continue + require = deepcopy(require) require.marker = require.marker.intersect(requirement.marker) if not require.marker.is_empty(): @@ -290,7 +298,9 @@ def get_project_dependencies( cls, project_requires: List[Dependency], locked_packages: List[Package], + extras: Optional[Union[bool, Sequence[str]]] = None, ) -> Iterable[Tuple[Package, Dependency]]: + extras = extras or False # group packages entries by name, this is required because requirement might use # different constraints. packages_by_name = {} @@ -323,6 +333,7 @@ def get_project_dependencies( nested_dependencies = cls.__walk_dependencies( dependencies=dependencies, packages_by_name=packages_by_name, + extras=extras, ) return nested_dependencies.items() @@ -368,6 +379,7 @@ def get_project_dependency_packages( for package, dependency in self.get_project_dependencies( project_requires=selected, locked_packages=repository.packages, + extras=extras, ): for extra in dependency.extras: package.requires_extras.append(extra)