installer.py: compute package_id from spec (#43485)
The installer runs `get_dependent_ids`, which follows edges outside the subdag that's being installed, so it returns a superset of the actual dependents. That's generally fine, except that it calls `s.package` on every dependent, which triggers a package class to be instantiated, which is a lot of work. Instead, compute the package id from the spec, since that's all that's used anyways and does not trigger *lots* of slow and redundant instantiations of package objects.
This commit is contained in:
		| @@ -119,7 +119,7 @@ def __init__(self, pkg_count: int): | |||||||
|         self.pkg_ids: Set[str] = set() |         self.pkg_ids: Set[str] = set() | ||||||
| 
 | 
 | ||||||
|     def next_pkg(self, pkg: "spack.package_base.PackageBase"): |     def next_pkg(self, pkg: "spack.package_base.PackageBase"): | ||||||
|         pkg_id = package_id(pkg) |         pkg_id = package_id(pkg.spec) | ||||||
| 
 | 
 | ||||||
|         if pkg_id not in self.pkg_ids: |         if pkg_id not in self.pkg_ids: | ||||||
|             self.pkg_num += 1 |             self.pkg_num += 1 | ||||||
| @@ -221,12 +221,12 @@ def _handle_external_and_upstream(pkg: "spack.package_base.PackageBase", explici | |||||||
|     # consists in module file generation and registration in the DB. |     # consists in module file generation and registration in the DB. | ||||||
|     if pkg.spec.external: |     if pkg.spec.external: | ||||||
|         _process_external_package(pkg, explicit) |         _process_external_package(pkg, explicit) | ||||||
|         _print_installed_pkg(f"{pkg.prefix} (external {package_id(pkg)})") |         _print_installed_pkg(f"{pkg.prefix} (external {package_id(pkg.spec)})") | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|     if pkg.spec.installed_upstream: |     if pkg.spec.installed_upstream: | ||||||
|         tty.verbose( |         tty.verbose( | ||||||
|             f"{package_id(pkg)} is installed in an upstream Spack instance at " |             f"{package_id(pkg.spec)} is installed in an upstream Spack instance at " | ||||||
|             f"{pkg.spec.prefix}" |             f"{pkg.spec.prefix}" | ||||||
|         ) |         ) | ||||||
|         _print_installed_pkg(pkg.prefix) |         _print_installed_pkg(pkg.prefix) | ||||||
| @@ -403,7 +403,7 @@ def _install_from_cache( | |||||||
|         return False |         return False | ||||||
|     t.stop() |     t.stop() | ||||||
| 
 | 
 | ||||||
|     pkg_id = package_id(pkg) |     pkg_id = package_id(pkg.spec) | ||||||
|     tty.debug(f"Successfully extracted {pkg_id} from binary cache") |     tty.debug(f"Successfully extracted {pkg_id} from binary cache") | ||||||
| 
 | 
 | ||||||
|     _write_timer_json(pkg, t, True) |     _write_timer_json(pkg, t, True) | ||||||
| @@ -484,7 +484,7 @@ def _process_binary_cache_tarball( | |||||||
|         if download_result is None: |         if download_result is None: | ||||||
|             return False |             return False | ||||||
| 
 | 
 | ||||||
|     tty.msg(f"Extracting {package_id(pkg)} from binary cache") |     tty.msg(f"Extracting {package_id(pkg.spec)} from binary cache") | ||||||
| 
 | 
 | ||||||
|     with timer.measure("install"), spack.util.path.filter_padding(): |     with timer.measure("install"), spack.util.path.filter_padding(): | ||||||
|         binary_distribution.extract_tarball(pkg.spec, download_result, force=False, timer=timer) |         binary_distribution.extract_tarball(pkg.spec, download_result, force=False, timer=timer) | ||||||
| @@ -513,7 +513,7 @@ def _try_install_from_binary_cache( | |||||||
|     if not spack.mirror.MirrorCollection(binary=True): |     if not spack.mirror.MirrorCollection(binary=True): | ||||||
|         return False |         return False | ||||||
| 
 | 
 | ||||||
|     tty.debug(f"Searching for binary cache of {package_id(pkg)}") |     tty.debug(f"Searching for binary cache of {package_id(pkg.spec)}") | ||||||
| 
 | 
 | ||||||
|     with timer.measure("search"): |     with timer.measure("search"): | ||||||
|         matches = binary_distribution.get_mirrors_for_spec(pkg.spec, index_only=True) |         matches = binary_distribution.get_mirrors_for_spec(pkg.spec, index_only=True) | ||||||
| @@ -610,7 +610,7 @@ def get_dependent_ids(spec: "spack.spec.Spec") -> List[str]: | |||||||
| 
 | 
 | ||||||
|     Returns: list of package ids |     Returns: list of package ids | ||||||
|     """ |     """ | ||||||
|     return [package_id(d.package) for d in spec.dependents()] |     return [package_id(d) for d in spec.dependents()] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def install_msg(name: str, pid: int, install_status: InstallStatus) -> str: | def install_msg(name: str, pid: int, install_status: InstallStatus) -> str: | ||||||
| @@ -720,7 +720,7 @@ def log(pkg: "spack.package_base.PackageBase") -> None: | |||||||
|     dump_packages(pkg.spec, packages_dir) |     dump_packages(pkg.spec, packages_dir) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def package_id(pkg: "spack.package_base.PackageBase") -> str: | def package_id(spec: "spack.spec.Spec") -> str: | ||||||
|     """A "unique" package identifier for installation purposes |     """A "unique" package identifier for installation purposes | ||||||
| 
 | 
 | ||||||
|     The identifier is used to track build tasks, locks, install, and |     The identifier is used to track build tasks, locks, install, and | ||||||
| @@ -732,10 +732,10 @@ def package_id(pkg: "spack.package_base.PackageBase") -> str: | |||||||
|     Args: |     Args: | ||||||
|         pkg: the package from which the identifier is derived |         pkg: the package from which the identifier is derived | ||||||
|     """ |     """ | ||||||
|     if not pkg.spec.concrete: |     if not spec.concrete: | ||||||
|         raise ValueError("Cannot provide a unique, readable id when the spec is not concretized.") |         raise ValueError("Cannot provide a unique, readable id when the spec is not concretized.") | ||||||
| 
 | 
 | ||||||
|     return f"{pkg.name}-{pkg.version}-{pkg.spec.dag_hash()}" |     return f"{spec.name}-{spec.version}-{spec.dag_hash()}" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BuildRequest: | class BuildRequest: | ||||||
| @@ -765,7 +765,7 @@ def __init__(self, pkg: "spack.package_base.PackageBase", install_args: dict): | |||||||
|         self.pkg.last_phase = install_args.pop("stop_at", None)  # type: ignore[attr-defined] |         self.pkg.last_phase = install_args.pop("stop_at", None)  # type: ignore[attr-defined] | ||||||
| 
 | 
 | ||||||
|         # Cache the package id for convenience |         # Cache the package id for convenience | ||||||
|         self.pkg_id = package_id(pkg) |         self.pkg_id = package_id(pkg.spec) | ||||||
| 
 | 
 | ||||||
|         # Save off the original install arguments plus standard defaults |         # Save off the original install arguments plus standard defaults | ||||||
|         # since they apply to the requested package *and* dependencies. |         # since they apply to the requested package *and* dependencies. | ||||||
| @@ -780,9 +780,9 @@ def __init__(self, pkg: "spack.package_base.PackageBase", install_args: dict): | |||||||
|         # are not able to return full dependents for all packages across |         # are not able to return full dependents for all packages across | ||||||
|         # environment specs. |         # environment specs. | ||||||
|         self.dependencies = set( |         self.dependencies = set( | ||||||
|             package_id(d.package) |             package_id(d) | ||||||
|             for d in self.pkg.spec.dependencies(deptype=self.get_depflags(self.pkg)) |             for d in self.pkg.spec.dependencies(deptype=self.get_depflags(self.pkg)) | ||||||
|             if package_id(d.package) != self.pkg_id |             if package_id(d) != self.pkg_id | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def __repr__(self) -> str: |     def __repr__(self) -> str: | ||||||
| @@ -832,7 +832,7 @@ def get_depflags(self, pkg: "spack.package_base.PackageBase") -> int: | |||||||
|         depflag = dt.LINK | dt.RUN |         depflag = dt.LINK | dt.RUN | ||||||
|         include_build_deps = self.install_args.get("include_build_deps") |         include_build_deps = self.install_args.get("include_build_deps") | ||||||
| 
 | 
 | ||||||
|         if self.pkg_id == package_id(pkg): |         if self.pkg_id == package_id(pkg.spec): | ||||||
|             cache_only = self.install_args.get("package_cache_only") |             cache_only = self.install_args.get("package_cache_only") | ||||||
|         else: |         else: | ||||||
|             cache_only = self.install_args.get("dependencies_cache_only") |             cache_only = self.install_args.get("dependencies_cache_only") | ||||||
| @@ -927,7 +927,7 @@ def __init__( | |||||||
|             raise ValueError(f"{self.pkg.name} must have a concrete spec") |             raise ValueError(f"{self.pkg.name} must have a concrete spec") | ||||||
| 
 | 
 | ||||||
|         # The "unique" identifier for the task's package |         # The "unique" identifier for the task's package | ||||||
|         self.pkg_id = package_id(self.pkg) |         self.pkg_id = package_id(self.pkg.spec) | ||||||
| 
 | 
 | ||||||
|         # The explicit build request associated with the package |         # The explicit build request associated with the package | ||||||
|         if not isinstance(request, BuildRequest): |         if not isinstance(request, BuildRequest): | ||||||
| @@ -965,9 +965,9 @@ def __init__( | |||||||
|         # if use traverse for transitive dependencies, then must remove |         # if use traverse for transitive dependencies, then must remove | ||||||
|         # transitive dependents on failure. |         # transitive dependents on failure. | ||||||
|         self.dependencies = set( |         self.dependencies = set( | ||||||
|             package_id(d.package) |             package_id(d) | ||||||
|             for d in self.pkg.spec.dependencies(deptype=self.request.get_depflags(self.pkg)) |             for d in self.pkg.spec.dependencies(deptype=self.request.get_depflags(self.pkg)) | ||||||
|             if package_id(d.package) != self.pkg_id |             if package_id(d) != self.pkg_id | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         # Handle bootstrapped compiler |         # Handle bootstrapped compiler | ||||||
| @@ -983,7 +983,7 @@ def __init__( | |||||||
|             dep.constrain(f"os={str(arch_spec.os)}") |             dep.constrain(f"os={str(arch_spec.os)}") | ||||||
|             dep.constrain(f"target={arch_spec.target.microarchitecture.family.name}:") |             dep.constrain(f"target={arch_spec.target.microarchitecture.family.name}:") | ||||||
|             dep.concretize() |             dep.concretize() | ||||||
|             dep_id = package_id(dep.package) |             dep_id = package_id(dep) | ||||||
|             self.dependencies.add(dep_id) |             self.dependencies.add(dep_id) | ||||||
| 
 | 
 | ||||||
|         # List of uninstalled dependencies, which is used to establish |         # List of uninstalled dependencies, which is used to establish | ||||||
| @@ -1194,7 +1194,7 @@ def _add_bootstrap_compilers( | |||||||
|         """ |         """ | ||||||
|         packages = _packages_needed_to_bootstrap_compiler(compiler, architecture, pkgs) |         packages = _packages_needed_to_bootstrap_compiler(compiler, architecture, pkgs) | ||||||
|         for comp_pkg, is_compiler in packages: |         for comp_pkg, is_compiler in packages: | ||||||
|             pkgid = package_id(comp_pkg) |             pkgid = package_id(comp_pkg.spec) | ||||||
|             if pkgid not in self.build_tasks: |             if pkgid not in self.build_tasks: | ||||||
|                 self._add_init_task(comp_pkg, request, is_compiler, all_deps) |                 self._add_init_task(comp_pkg, request, is_compiler, all_deps) | ||||||
|             elif is_compiler: |             elif is_compiler: | ||||||
| @@ -1241,7 +1241,7 @@ def _add_init_task( | |||||||
|         """ |         """ | ||||||
|         task = BuildTask(pkg, request, is_compiler, 0, 0, STATUS_ADDED, self.installed) |         task = BuildTask(pkg, request, is_compiler, 0, 0, STATUS_ADDED, self.installed) | ||||||
|         for dep_id in task.dependencies: |         for dep_id in task.dependencies: | ||||||
|             all_deps[dep_id].add(package_id(pkg)) |             all_deps[dep_id].add(package_id(pkg.spec)) | ||||||
| 
 | 
 | ||||||
|         self._push_task(task) |         self._push_task(task) | ||||||
| 
 | 
 | ||||||
| @@ -1276,7 +1276,7 @@ def _check_deps_status(self, request: BuildRequest) -> None: | |||||||
|         err = "Cannot proceed with {0}: {1}" |         err = "Cannot proceed with {0}: {1}" | ||||||
|         for dep in request.traverse_dependencies(): |         for dep in request.traverse_dependencies(): | ||||||
|             dep_pkg = dep.package |             dep_pkg = dep.package | ||||||
|             dep_id = package_id(dep_pkg) |             dep_id = package_id(dep) | ||||||
| 
 | 
 | ||||||
|             # Check for failure since a prefix lock is not required |             # Check for failure since a prefix lock is not required | ||||||
|             if spack.store.STORE.failure_tracker.has_failed(dep): |             if spack.store.STORE.failure_tracker.has_failed(dep): | ||||||
| @@ -1409,7 +1409,7 @@ def _cleanup_task(self, pkg: "spack.package_base.PackageBase") -> None: | |||||||
|         Args: |         Args: | ||||||
|             pkg: the package being installed |             pkg: the package being installed | ||||||
|         """ |         """ | ||||||
|         self._remove_task(package_id(pkg)) |         self._remove_task(package_id(pkg.spec)) | ||||||
| 
 | 
 | ||||||
|         # Ensure we have a read lock to prevent others from uninstalling the |         # Ensure we have a read lock to prevent others from uninstalling the | ||||||
|         # spec during our installation. |         # spec during our installation. | ||||||
| @@ -1423,7 +1423,7 @@ def _ensure_install_ready(self, pkg: "spack.package_base.PackageBase") -> None: | |||||||
|         Args: |         Args: | ||||||
|             pkg: the package being locally installed |             pkg: the package being locally installed | ||||||
|         """ |         """ | ||||||
|         pkg_id = package_id(pkg) |         pkg_id = package_id(pkg.spec) | ||||||
|         pre = f"{pkg_id} cannot be installed locally:" |         pre = f"{pkg_id} cannot be installed locally:" | ||||||
| 
 | 
 | ||||||
|         # External packages cannot be installed locally. |         # External packages cannot be installed locally. | ||||||
| @@ -1465,7 +1465,7 @@ def _ensure_locked( | |||||||
|             "write", |             "write", | ||||||
|         ], f'"{lock_type}" is not a supported package management lock type' |         ], f'"{lock_type}" is not a supported package management lock type' | ||||||
| 
 | 
 | ||||||
|         pkg_id = package_id(pkg) |         pkg_id = package_id(pkg.spec) | ||||||
|         ltype, lock = self.locks.get(pkg_id, (lock_type, None)) |         ltype, lock = self.locks.get(pkg_id, (lock_type, None)) | ||||||
|         if lock and ltype == lock_type: |         if lock and ltype == lock_type: | ||||||
|             return ltype, lock |             return ltype, lock | ||||||
| @@ -1601,7 +1601,7 @@ def _add_tasks(self, request: BuildRequest, all_deps): | |||||||
|             for dep in request.traverse_dependencies(): |             for dep in request.traverse_dependencies(): | ||||||
|                 dep_pkg = dep.package |                 dep_pkg = dep.package | ||||||
| 
 | 
 | ||||||
|                 dep_id = package_id(dep_pkg) |                 dep_id = package_id(dep) | ||||||
|                 if dep_id not in self.build_tasks: |                 if dep_id not in self.build_tasks: | ||||||
|                     self._add_init_task(dep_pkg, request, False, all_deps) |                     self._add_init_task(dep_pkg, request, False, all_deps) | ||||||
| 
 | 
 | ||||||
| @@ -1913,7 +1913,7 @@ def _flag_installed( | |||||||
|             dependent_ids: set of the package's dependent ids, or None if the dependent ids are |             dependent_ids: set of the package's dependent ids, or None if the dependent ids are | ||||||
|                 limited to those maintained in the package (dependency DAG) |                 limited to those maintained in the package (dependency DAG) | ||||||
|         """ |         """ | ||||||
|         pkg_id = package_id(pkg) |         pkg_id = package_id(pkg.spec) | ||||||
| 
 | 
 | ||||||
|         if pkg_id in self.installed: |         if pkg_id in self.installed: | ||||||
|             # Already determined the package has been installed |             # Already determined the package has been installed | ||||||
| @@ -2309,7 +2309,7 @@ def __init__(self, pkg: "spack.package_base.PackageBase", install_args: dict): | |||||||
| 
 | 
 | ||||||
|         # info/debug information |         # info/debug information | ||||||
|         self.pre = _log_prefix(pkg.name) |         self.pre = _log_prefix(pkg.name) | ||||||
|         self.pkg_id = package_id(pkg) |         self.pkg_id = package_id(pkg.spec) | ||||||
| 
 | 
 | ||||||
|     def run(self) -> bool: |     def run(self) -> bool: | ||||||
|         """Main entry point from ``build_process`` to kick off install in child.""" |         """Main entry point from ``build_process`` to kick off install in child.""" | ||||||
|   | |||||||
| @@ -136,7 +136,7 @@ def test_get_dependent_ids(install_mockery, mock_packages): | |||||||
|     spec.concretize() |     spec.concretize() | ||||||
|     assert spec.concrete |     assert spec.concrete | ||||||
| 
 | 
 | ||||||
|     pkg_id = inst.package_id(spec.package) |     pkg_id = inst.package_id(spec) | ||||||
| 
 | 
 | ||||||
|     # Grab the sole dependency of 'a', which is 'b' |     # Grab the sole dependency of 'a', which is 'b' | ||||||
|     dep = spec.dependencies()[0] |     dep = spec.dependencies()[0] | ||||||
| @@ -385,7 +385,7 @@ def test_ensure_locked_have(install_mockery, tmpdir, capsys): | |||||||
|     const_arg = installer_args(["trivial-install-test-package"], {}) |     const_arg = installer_args(["trivial-install-test-package"], {}) | ||||||
|     installer = create_installer(const_arg) |     installer = create_installer(const_arg) | ||||||
|     spec = installer.build_requests[0].pkg.spec |     spec = installer.build_requests[0].pkg.spec | ||||||
|     pkg_id = inst.package_id(spec.package) |     pkg_id = inst.package_id(spec) | ||||||
| 
 | 
 | ||||||
|     with tmpdir.as_cwd(): |     with tmpdir.as_cwd(): | ||||||
|         # Test "downgrade" of a read lock (to a read lock) |         # Test "downgrade" of a read lock (to a read lock) | ||||||
| @@ -456,17 +456,15 @@ def _pl(db, spec, timeout): | |||||||
| 
 | 
 | ||||||
| def test_package_id_err(install_mockery): | def test_package_id_err(install_mockery): | ||||||
|     s = spack.spec.Spec("trivial-install-test-package") |     s = spack.spec.Spec("trivial-install-test-package") | ||||||
|     pkg_cls = spack.repo.PATH.get_pkg_class(s.name) |  | ||||||
|     with pytest.raises(ValueError, match="spec is not concretized"): |     with pytest.raises(ValueError, match="spec is not concretized"): | ||||||
|         inst.package_id(pkg_cls(s)) |         inst.package_id(s) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_package_id_ok(install_mockery): | def test_package_id_ok(install_mockery): | ||||||
|     spec = spack.spec.Spec("trivial-install-test-package") |     spec = spack.spec.Spec("trivial-install-test-package") | ||||||
|     spec.concretize() |     spec.concretize() | ||||||
|     assert spec.concrete |     assert spec.concrete | ||||||
|     pkg = spec.package |     assert spec.name in inst.package_id(spec) | ||||||
|     assert pkg.name in inst.package_id(pkg) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_fake_install(install_mockery): | def test_fake_install(install_mockery): | ||||||
| @@ -726,7 +724,7 @@ def test_check_deps_status_external(install_mockery, monkeypatch): | |||||||
|     installer._check_deps_status(request) |     installer._check_deps_status(request) | ||||||
| 
 | 
 | ||||||
|     for dep in request.spec.traverse(root=False): |     for dep in request.spec.traverse(root=False): | ||||||
|         assert inst.package_id(dep.package) in installer.installed |         assert inst.package_id(dep) in installer.installed | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_check_deps_status_upstream(install_mockery, monkeypatch): | def test_check_deps_status_upstream(install_mockery, monkeypatch): | ||||||
| @@ -739,7 +737,7 @@ def test_check_deps_status_upstream(install_mockery, monkeypatch): | |||||||
|     installer._check_deps_status(request) |     installer._check_deps_status(request) | ||||||
| 
 | 
 | ||||||
|     for dep in request.spec.traverse(root=False): |     for dep in request.spec.traverse(root=False): | ||||||
|         assert inst.package_id(dep.package) in installer.installed |         assert inst.package_id(dep) in installer.installed | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_add_bootstrap_compilers(install_mockery, monkeypatch): | def test_add_bootstrap_compilers(install_mockery, monkeypatch): | ||||||
| @@ -1111,7 +1109,7 @@ def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys): | |||||||
|     const_arg = installer_args(["b"], {"fail_fast": False}) |     const_arg = installer_args(["b"], {"fail_fast": False}) | ||||||
|     const_arg.extend(installer_args(["c"], {"fail_fast": True})) |     const_arg.extend(installer_args(["c"], {"fail_fast": True})) | ||||||
|     installer = create_installer(const_arg) |     installer = create_installer(const_arg) | ||||||
|     pkg_ids = [inst.package_id(spec.package) for spec, _ in const_arg] |     pkg_ids = [inst.package_id(spec) for spec, _ in const_arg] | ||||||
| 
 | 
 | ||||||
|     # Make sure all packages are identified as failed |     # Make sure all packages are identified as failed | ||||||
|     # |     # | ||||||
| @@ -1186,7 +1184,7 @@ def test_install_lock_installed_requeue(install_mockery, monkeypatch, capfd): | |||||||
|     const_arg = installer_args(["b"], {}) |     const_arg = installer_args(["b"], {}) | ||||||
|     b, _ = const_arg[0] |     b, _ = const_arg[0] | ||||||
|     installer = create_installer(const_arg) |     installer = create_installer(const_arg) | ||||||
|     b_pkg_id = inst.package_id(b.package) |     b_pkg_id = inst.package_id(b) | ||||||
| 
 | 
 | ||||||
|     def _prep(installer, task): |     def _prep(installer, task): | ||||||
|         installer.installed.add(b_pkg_id) |         installer.installed.add(b_pkg_id) | ||||||
| @@ -1196,7 +1194,7 @@ def _prep(installer, task): | |||||||
|         monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked) |         monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked) | ||||||
| 
 | 
 | ||||||
|     def _requeued(installer, task, install_status): |     def _requeued(installer, task, install_status): | ||||||
|         tty.msg("requeued {0}".format(inst.package_id(task.pkg))) |         tty.msg("requeued {0}".format(inst.package_id(task.pkg.spec))) | ||||||
| 
 | 
 | ||||||
|     # Flag the package as installed |     # Flag the package as installed | ||||||
|     monkeypatch.setattr(inst.PackageInstaller, "_prepare_for_install", _prep) |     monkeypatch.setattr(inst.PackageInstaller, "_prepare_for_install", _prep) | ||||||
| @@ -1262,7 +1260,7 @@ def test_install_skip_patch(install_mockery, mock_fetch): | |||||||
|     installer.install() |     installer.install() | ||||||
| 
 | 
 | ||||||
|     spec, install_args = const_arg[0] |     spec, install_args = const_arg[0] | ||||||
|     assert inst.package_id(spec.package) in installer.installed |     assert inst.package_id(spec) in installer.installed | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_install_implicit(install_mockery, mock_fetch): | def test_install_implicit(install_mockery, mock_fetch): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Harmen Stoppels
					Harmen Stoppels