Compare commits

...

5 Commits

Author SHA1 Message Date
Harmen Stoppels
ecf882c240 fix fullnames 2025-04-25 13:52:09 +02:00
Harmen Stoppels
6822db0fe7 inline packages definitions dont have a name 2025-04-25 13:33:21 +02:00
Harmen Stoppels
868d538958 simplify and speed up external list 2025-04-25 11:53:07 +02:00
Harmen Stoppels
57ac37eb67 set __module__ prop so it's usable in init 2025-04-25 11:48:58 +02:00
Harmen Stoppels
4779322247 package_base.py: correctly compute package name 2025-04-25 11:48:58 +02:00
6 changed files with 60 additions and 44 deletions

View File

@ -121,6 +121,7 @@ def __init__(self, wrapped_pkg_object, root_builder):
new_cls_name,
bases,
{
"__module__": package_cls.__module__,
"run_tests": property(lambda x: x.wrapped_package_object.run_tests),
"test_requires_compiler": property(
lambda x: x.wrapped_package_object.test_requires_compiler
@ -129,7 +130,6 @@ def __init__(self, wrapped_pkg_object, root_builder):
"tester": property(lambda x: x.wrapped_package_object.tester),
},
)
new_cls.__module__ = package_cls.__module__
self.__class__ = new_cls
self.__dict__.update(wrapped_pkg_object.__dict__)

View File

@ -5,7 +5,7 @@
import errno
import os
import re
import sys
from collections import defaultdict
from typing import List, Optional, Set
import llnl.util.tty as tty
@ -17,7 +17,6 @@
import spack.cray_manifest as cray_manifest
import spack.detection
import spack.error
import spack.package_base
import spack.repo
import spack.spec
from spack.cmd.common import arguments
@ -246,13 +245,16 @@ def _collect_and_consume_cray_manifest_files(
def external_list(args):
# Trigger a read of all packages, might take a long time.
list(spack.repo.PATH.all_package_classes())
# Print all the detectable packages
tty.msg("Detectable packages per repository")
for namespace, pkgs in sorted(spack.package_base.detectable_packages.items()):
repo_to_packages = defaultdict(list)
for fullname in spack.repo.PATH.packages_with_tags("detectable", full=True):
repo, _, pkg = fullname.rpartition(".")
repo_to_packages[repo].append(pkg)
for namespace in sorted(repo_to_packages):
print("Repository:", namespace)
colify.colify(pkgs, indent=4, output=sys.stdout)
colify.colify(repo_to_packages[namespace], indent=4)
def external(parser, args):

View File

@ -132,11 +132,6 @@ def windows_establish_runtime_linkage(self):
win_rpath.establish_link()
#: Registers which are the detectable packages, by repo and package name
#: Need a pass of package repositories to be filled.
detectable_packages = collections.defaultdict(list)
class DetectablePackageMeta(type):
"""Check if a package is detectable and add default implementations
for the detection function.
@ -242,9 +237,6 @@ def determine_spec_details(cls, prefix, objs_in_prefix):
def determine_variants(cls, objs, version_str):
return ""
# Register the class as a detectable package
detectable_packages[cls.namespace].append(cls.name)
# Attach function implementations to the detectable class
default = False
if not hasattr(cls, "determine_spec_details"):
@ -839,26 +831,17 @@ def fullname(cls):
def fullnames(cls):
"""Fullnames for this package and any packages from which it inherits."""
fullnames = []
for cls in cls.__mro__:
namespace = getattr(cls, "namespace", None)
if namespace:
fullnames.append("%s.%s" % (namespace, cls.name))
if namespace == "builtin":
# builtin packages cannot inherit from other repos
for base in cls.__mro__:
if not base.__module__.startswith(f"{spack.repo.ROOT_PYTHON_NAMESPACE}."):
break
fullnames.append(base.fullname)
return fullnames
@classproperty
def name(cls):
"""The name of this package.
The name of a package is the name of its Python module, without
the containing module names.
"""
"""The canonical name of this package"""
if cls._name is None:
cls._name = cls.module.__name__
if "." in cls._name:
cls._name = cls._name[cls._name.rindex(".") + 1 :]
cls._name = spack.repo.pkg_name_from_module(cls.__module__)
return cls._name
@classproperty

View File

@ -83,6 +83,21 @@ def namespace_from_fullname(fullname):
return namespace
def pkg_name_from_module(module_name: str) -> str:
"""Return the actual package name from a module name.
For instance ``spack.pkg.builtin.num3dtk`` has package name ``3dtk``
and ``spack.pkg.builtin.py_numpy`` has package name ``py-numpy``
"""
if not module_name.startswith(f"{ROOT_PYTHON_NAMESPACE}."):
raise ValueError(f"Module '{module_name}' is not a Spack package module")
namespace, _, import_name = module_name[len(ROOT_PYTHON_NAMESPACE) + 1 :].rpartition(".")
name = PATH.get_repo(namespace).real_name(import_name)
if name is None:
raise ValueError(f"Module '{module_name}' does not correspond to a known package")
return name
class SpackNamespaceLoader:
def create_module(self, spec):
return SpackNamespace(spec.name)

View File

@ -9,6 +9,7 @@
"""
import os
import pathlib
import shutil
import pytest
@ -22,6 +23,7 @@
import spack.install_test
import spack.package
import spack.package_base
import spack.repo
import spack.spec
import spack.store
from spack.build_systems.generic import Package
@ -245,23 +247,31 @@ class BadDetectablePackage(spack.package.Package):
libraries = ["libFindMe.a"]
def test_package_url_and_urls():
class URLsPackage(spack.package.Package):
def test_package_url_and_urls(tmp_path: pathlib.Path):
repo_path = tmp_path / "test-repo"
spack.repo.create_repo(str(repo_path))
package_py = repo_path / "packages" / "urls-package" / "package.py"
package_py.parent.mkdir(parents=True)
package_py.write_text(
"""\
from spack.package import *
class UrlsPackage(Package):
url = "https://www.example.com/url-package-1.0.tgz"
urls = ["https://www.example.com/archive"]
"""
)
s = spack.spec.Spec("pkg-a")
with spack.repo.use_repositories(str(repo_path)) as repo:
pkg_cls = repo.get_pkg_class("urls-package")
s = spack.spec.Spec("urls-package")
with pytest.raises(ValueError, match="defines both"):
URLsPackage(s)
pkg_cls(s)
def test_package_license():
class LicensedPackage(spack.package.Package):
extendees = None # currently a required attribute for is_extension()
license_files = None
def test_package_license(mock_packages):
s = spack.spec.Spec("pkg-a")
pkg = LicensedPackage(s)
pkg = spack.repo.PATH.get_pkg_class("pkg-a")(s)
assert pkg.global_license_file is None
pkg.license_files = ["license.txt"]

View File

@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import importlib
import os
import pytest
@ -333,3 +334,8 @@ def test_package_can_have_sparse_checkout_properties(mock_packages, mock_fetch,
assert isinstance(fetcher, spack.fetch_strategy.GitFetchStrategy)
assert hasattr(fetcher, "git_sparse_paths")
assert fetcher.git_sparse_paths == pkg_cls.git_sparse_paths
def test_package_name_from_class_type(mock_packages):
module = importlib.import_module("spack.pkg.builtin.mock.num7zip")
assert module._7zip.name == "7zip"