diff --git a/.github/workflows/docs-ci.yml b/.github/workflows/docs-ci.yml
index 8c2abfe..621de4b 100644
--- a/.github/workflows/docs-ci.yml
+++ b/.github/workflows/docs-ci.yml
@@ -4,19 +4,19 @@ on: [push, pull_request]
jobs:
build:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
strategy:
max-parallel: 4
matrix:
- python-version: [3.9]
+ python-version: [3.12]
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml
index d2206c8..a66c9c8 100644
--- a/.github/workflows/pypi-release.yml
+++ b/.github/workflows/pypi-release.yml
@@ -21,14 +21,14 @@ on:
jobs:
build-pypi-distribs:
name: Build and publish library to PyPI
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
- python-version: 3.9
+ python-version: 3.12
- name: Install pypa/build
run: python -m pip install build --user
@@ -37,7 +37,7 @@ jobs:
run: python -m build --sdist --wheel --outdir dist/
- name: Upload built archives
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: pypi_archives
path: dist/*
@@ -47,17 +47,17 @@ jobs:
name: Create GH release
needs:
- build-pypi-distribs
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- name: Download built archives
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: pypi_archives
path: dist
- name: Create GH release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
with:
draft: true
files: dist/*
@@ -67,11 +67,11 @@ jobs:
name: Create PyPI release
needs:
- create-gh-release
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- name: Download built archives
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: pypi_archives
path: dist
diff --git a/Makefile b/Makefile
index c4c1d09..3394b21 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
@@ -47,8 +47,3 @@ test:
@echo "-> Run the test suite"
PYTHONPATH=src ${VENV}/bin/pytest tests -vvs
-#docs:
-# rm -rf docs/_build/
-# @${ACTIVATE} sphinx-build docs/ docs/_build/
-#
-#.PHONY: conf dev check valid black isort clean test docs
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 7b3945c..0b21ce5 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -7,43 +7,35 @@
jobs:
- - template: etc/ci/azure-posix.yml
- parameters:
- job_name: ubuntu20_cpython
- image_name: ubuntu-20.04
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
- test_suites:
- all: venv/bin/pytest -n 2 -vvs tests
-
- template: etc/ci/azure-posix.yml
parameters:
job_name: ubuntu22_cpython
image_name: ubuntu-22.04
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv/bin/pytest -n 2 -vvs tests
- template: etc/ci/azure-posix.yml
parameters:
- job_name: macos12_cpython
- image_name: macOS-12
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ job_name: ubuntu24_cpython
+ image_name: ubuntu-24.04
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv/bin/pytest -n 2 -vvs tests
- template: etc/ci/azure-posix.yml
parameters:
job_name: macos13_cpython
- image_name: macOS-13
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ image_name: macos-13
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv/bin/pytest -n 2 -vvs tests
- template: etc/ci/azure-posix.yml
parameters:
- job_name: macos14_cpython
- image_name: macOS-14
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ job_name: macos14_cpython_arm64
+ image_name: macos-14
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv/bin/pytest -n 2 -vvs tests
@@ -51,7 +43,7 @@ jobs:
parameters:
job_name: win2019_cpython
image_name: windows-2019
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv\Scripts\pytest -n 2 -vvs tests
@@ -59,6 +51,6 @@ jobs:
parameters:
job_name: win2022_cpython
image_name: windows-2022
- python_versions: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ python_versions: ['3.9', '3.10', '3.11', '3.12', '3.13']
test_suites:
all: venv\Scripts\pytest -n 2 -vvs tests
diff --git a/etc/scripts/check_thirdparty.py b/etc/scripts/check_thirdparty.py
index b052f25..2daded9 100644
--- a/etc/scripts/check_thirdparty.py
+++ b/etc/scripts/check_thirdparty.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import click
@@ -17,7 +17,8 @@
@click.option(
"-d",
"--dest",
- type=click.Path(exists=True, readable=True, path_type=str, file_okay=False),
+ type=click.Path(exists=True, readable=True,
+ path_type=str, file_okay=False),
required=True,
help="Path to the thirdparty directory to check.",
)
diff --git a/etc/scripts/fetch_thirdparty.py b/etc/scripts/fetch_thirdparty.py
index eedf05c..3f9ff52 100644
--- a/etc/scripts/fetch_thirdparty.py
+++ b/etc/scripts/fetch_thirdparty.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
@@ -55,7 +55,8 @@
"-d",
"--dest",
"dest_dir",
- type=click.Path(exists=True, readable=True, path_type=str, file_okay=False),
+ type=click.Path(exists=True, readable=True,
+ path_type=str, file_okay=False),
metavar="DIR",
default=utils_thirdparty.THIRDPARTY_DIR,
show_default=True,
@@ -224,7 +225,8 @@ def fetch_thirdparty(
environments = None
if wheels:
evts = itertools.product(python_versions, operating_systems)
- environments = [utils_thirdparty.Environment.from_pyver_and_os(pyv, os) for pyv, os in evts]
+ environments = [utils_thirdparty.Environment.from_pyver_and_os(
+ pyv, os) for pyv, os in evts]
# Collect PyPI repos
repos = []
@@ -260,13 +262,14 @@ def fetch_thirdparty(
repos=repos,
)
if not fetched:
- wheels_or_sdist_not_found[f"{name}=={version}"].append(environment)
+ wheels_or_sdist_not_found[f"{name}=={version}"].append(
+ environment)
if TRACE:
print(f" NOT FOUND")
if (sdists or
(f"{name}=={version}" in wheels_or_sdist_not_found and name in sdist_only)
- ):
+ ):
if TRACE:
print(f" ==> Fetching sdist: {name}=={version}")
@@ -289,7 +292,8 @@ def fetch_thirdparty(
sdist_missing = sdists and "sdist" in dists and not name in wheel_only
if sdist_missing:
mia.append(f"SDist missing: {nv} {dists}")
- wheels_missing = wheels and any(d for d in dists if d != "sdist") and not name in sdist_only
+ wheels_missing = wheels and any(
+ d for d in dists if d != "sdist") and not name in sdist_only
if wheels_missing:
mia.append(f"Wheels missing: {nv} {dists}")
@@ -299,7 +303,8 @@ def fetch_thirdparty(
raise Exception(mia)
print(f"==> FETCHING OR CREATING ABOUT AND LICENSE FILES")
- utils_thirdparty.fetch_abouts_and_licenses(dest_dir=dest_dir, use_cached_index=use_cached_index)
+ utils_thirdparty.fetch_abouts_and_licenses(
+ dest_dir=dest_dir, use_cached_index=use_cached_index)
utils_thirdparty.clean_about_files(dest_dir=dest_dir)
# check for problems
diff --git a/etc/scripts/gen_requirements.py b/etc/scripts/gen_requirements.py
index 07e26f7..2b65ae8 100644
--- a/etc/scripts/gen_requirements.py
+++ b/etc/scripts/gen_requirements.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import argparse
diff --git a/etc/scripts/gen_requirements_dev.py b/etc/scripts/gen_requirements_dev.py
index 12cc06d..5db1c48 100644
--- a/etc/scripts/gen_requirements_dev.py
+++ b/etc/scripts/gen_requirements_dev.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import argparse
diff --git a/etc/scripts/utils_dejacode.py b/etc/scripts/utils_dejacode.py
index c42e6c9..652252d 100644
--- a/etc/scripts/utils_dejacode.py
+++ b/etc/scripts/utils_dejacode.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import io
@@ -33,7 +33,8 @@
def can_do_api_calls():
if not DEJACODE_API_KEY and DEJACODE_API_URL:
- print("DejaCode DEJACODE_API_KEY and DEJACODE_API_URL not configured. Doing nothing")
+ print(
+ "DejaCode DEJACODE_API_KEY and DEJACODE_API_URL not configured. Doing nothing")
return False
else:
return True
@@ -68,7 +69,8 @@ def get_package_data(distribution):
return results[0]
elif len_results > 1:
- print(f"More than 1 entry exists, review at: {DEJACODE_API_URL_PACKAGES}")
+ print(
+ f"More than 1 entry exists, review at: {DEJACODE_API_URL_PACKAGES}")
else:
print("Could not find package:", distribution.download_url)
@@ -149,7 +151,8 @@ def find_latest_dejacode_package(distribution):
# there was no exact match, find the latest version
# TODO: consider the closest version rather than the latest
# or the version that has the best data
- with_versions = [(packaging_version.parse(p["version"]), p) for p in packages]
+ with_versions = [(packaging_version.parse(p["version"]), p)
+ for p in packages]
with_versions = sorted(with_versions)
latest_version, latest_package_version = sorted(with_versions)[-1]
print(
diff --git a/etc/scripts/utils_requirements.py b/etc/scripts/utils_requirements.py
index 0fc25a3..1c50239 100644
--- a/etc/scripts/utils_requirements.py
+++ b/etc/scripts/utils_requirements.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
@@ -102,7 +102,8 @@ def lock_dev_requirements(
all_req_nvs = get_required_name_versions(all_req_lines)
dev_only_req_nvs = {n: v for n, v in all_req_nvs if n not in main_names}
- new_reqs = "\n".join(f"{n}=={v}" for n, v in sorted(dev_only_req_nvs.items()))
+ new_reqs = "\n".join(
+ f"{n}=={v}" for n, v in sorted(dev_only_req_nvs.items()))
with open(dev_requirements_file, "w") as fo:
fo.write(new_reqs)
@@ -113,10 +114,12 @@ def get_installed_reqs(site_packages_dir):
as a text.
"""
if not os.path.exists(site_packages_dir):
- raise Exception(f"site_packages directory: {site_packages_dir!r} does not exists")
+ raise Exception(
+ f"site_packages directory: {site_packages_dir!r} does not exists")
# Also include these packages in the output with --all: wheel, distribute,
# setuptools, pip
- args = ["pip", "freeze", "--exclude-editable", "--all", "--path", site_packages_dir]
+ args = ["pip", "freeze", "--exclude-editable",
+ "--all", "--path", site_packages_dir]
return subprocess.check_output(args, encoding="utf-8")
diff --git a/etc/scripts/utils_thirdparty.py b/etc/scripts/utils_thirdparty.py
index addf8e5..46dc728 100644
--- a/etc/scripts/utils_thirdparty.py
+++ b/etc/scripts/utils_thirdparty.py
@@ -5,7 +5,7 @@
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
-# See https://github.com/nexB/skeleton for support or download.
+# See https://github.com/aboutcode-org/skeleton for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import email
@@ -245,9 +245,11 @@ def download_wheel(name, version, environment, dest_dir=THIRDPARTY_DIR, repos=tu
package = repo.get_package_version(name=name, version=version)
if not package:
if TRACE_DEEP:
- print(f" download_wheel: No package in {repo.index_url} for {name}=={version}")
+ print(
+ f" download_wheel: No package in {repo.index_url} for {name}=={version}")
continue
- supported_wheels = list(package.get_supported_wheels(environment=environment))
+ supported_wheels = list(
+ package.get_supported_wheels(environment=environment))
if not supported_wheels:
if TRACE_DEEP:
print(
@@ -291,7 +293,8 @@ def download_sdist(name, version, dest_dir=THIRDPARTY_DIR, repos=tuple()):
if not package:
if TRACE_DEEP:
- print(f" download_sdist: No package in {repo.index_url} for {name}=={version}")
+ print(
+ f" download_sdist: No package in {repo.index_url} for {name}=={version}")
continue
sdist = package.sdist
if not sdist:
@@ -300,7 +303,8 @@ def download_sdist(name, version, dest_dir=THIRDPARTY_DIR, repos=tuple()):
continue
if TRACE_DEEP:
- print(f" download_sdist: Getting sdist from index (or cache): {sdist.download_url}")
+ print(
+ f" download_sdist: Getting sdist from index (or cache): {sdist.download_url}")
fetched_sdist_filename = package.sdist.download(dest_dir=dest_dir)
if fetched_sdist_filename:
@@ -533,7 +537,8 @@ def get_best_download_url(self, repos=tuple()):
repos = DEFAULT_PYPI_REPOS
for repo in repos:
- package = repo.get_package_version(name=self.name, version=self.version)
+ package = repo.get_package_version(
+ name=self.name, version=self.version)
if not package:
if TRACE:
print(
@@ -772,7 +777,8 @@ def load_remote_about_data(self):
if notice_text:
about_data["notice_text"] = notice_text
except RemoteNotFetchedException:
- print(f"Failed to fetch NOTICE file: {self.notice_download_url}")
+ print(
+ f"Failed to fetch NOTICE file: {self.notice_download_url}")
return self.load_about_data(about_data)
def get_checksums(self, dest_dir=THIRDPARTY_DIR):
@@ -821,9 +827,11 @@ def fetch_license_files(self, dest_dir=THIRDPARTY_DIR, use_cached_index=False):
Fetch license files if missing in `dest_dir`.
Return True if license files were fetched.
"""
- urls = LinksRepository.from_url(use_cached_index=use_cached_index).links
+ urls = LinksRepository.from_url(
+ use_cached_index=use_cached_index).links
errors = []
- extra_lic_names = [l.get("file") for l in self.extra_data.get("licenses", {})]
+ extra_lic_names = [l.get("file")
+ for l in self.extra_data.get("licenses", {})]
extra_lic_names += [self.extra_data.get("license_file")]
extra_lic_names = [ln for ln in extra_lic_names if ln]
lic_names = [f"{key}.LICENSE" for key in self.get_license_keys()]
@@ -834,7 +842,8 @@ def fetch_license_files(self, dest_dir=THIRDPARTY_DIR, use_cached_index=False):
try:
# try remotely first
- lic_url = get_license_link_for_filename(filename=filename, urls=urls)
+ lic_url = get_license_link_for_filename(
+ filename=filename, urls=urls)
fetch_and_save(
path_or_url=lic_url,
@@ -911,7 +920,8 @@ def load_pkginfo_data(self, dest_dir=THIRDPARTY_DIR):
c for c in classifiers if c.startswith("License")
]
license_expression = get_license_expression(declared_license)
- other_classifiers = [c for c in classifiers if not c.startswith("License")]
+ other_classifiers = [
+ c for c in classifiers if not c.startswith("License")]
holder = raw_data["Author"]
holder_contact = raw_data["Author-email"]
@@ -953,7 +963,8 @@ def update(self, data, overwrite=False, keep_extra=True):
package_url = data.get("package_url")
if package_url:
purl_from_data = packageurl.PackageURL.from_string(package_url)
- purl_from_self = packageurl.PackageURL.from_string(self.package_url)
+ purl_from_self = packageurl.PackageURL.from_string(
+ self.package_url)
if purl_from_data != purl_from_self:
print(
f"Invalid dist update attempt, no same same purl with dist: "
@@ -1003,7 +1014,8 @@ def get_license_link_for_filename(filename, urls):
if not path_or_url:
raise Exception(f"Missing link to file: {filename}")
if not len(path_or_url) == 1:
- raise Exception(f"Multiple links to file: {filename}: \n" + "\n".join(path_or_url))
+ raise Exception(
+ f"Multiple links to file: {filename}: \n" + "\n".join(path_or_url))
return path_or_url[0]
@@ -1397,7 +1409,8 @@ def packages_from_dir(cls, directory):
"""
base = os.path.abspath(directory)
- paths = [os.path.join(base, f) for f in os.listdir(base) if f.endswith(EXTENSIONS)]
+ paths = [os.path.join(base, f)
+ for f in os.listdir(base) if f.endswith(EXTENSIONS)]
if TRACE_ULTRA_DEEP:
print("packages_from_dir: paths:", paths)
@@ -1458,7 +1471,8 @@ def dists_from_paths_or_urls(cls, paths_or_urls):
dists = []
if TRACE_ULTRA_DEEP:
print(" ###paths_or_urls:", paths_or_urls)
- installable = [f for f in paths_or_urls if f.endswith(EXTENSIONS_INSTALLABLE)]
+ installable = [f for f in paths_or_urls if f.endswith(
+ EXTENSIONS_INSTALLABLE)]
for path_or_url in installable:
try:
dist = Distribution.from_path_or_url(path_or_url)
@@ -1476,7 +1490,8 @@ def dists_from_paths_or_urls(cls, paths_or_urls):
)
except InvalidDistributionFilename:
if TRACE_DEEP:
- print(f" Skipping invalid distribution from: {path_or_url}")
+ print(
+ f" Skipping invalid distribution from: {path_or_url}")
continue
return dists
@@ -1525,7 +1540,8 @@ class Environment:
implementation = attr.ib(
type=str,
default="cp",
- metadata=dict(help="Python implementation supported by this environment."),
+ metadata=dict(
+ help="Python implementation supported by this environment."),
repr=False,
)
@@ -1539,7 +1555,8 @@ class Environment:
platforms = attr.ib(
type=list,
default=attr.Factory(list),
- metadata=dict(help="List of platform tags supported by this environment."),
+ metadata=dict(
+ help="List of platform tags supported by this environment."),
repr=False,
)
@@ -1623,7 +1640,8 @@ class PypiSimpleRepository:
fetched_package_normalized_names = attr.ib(
type=set,
default=attr.Factory(set),
- metadata=dict(help="A set of already fetched package normalized names."),
+ metadata=dict(
+ help="A set of already fetched package normalized names."),
)
use_cached_index = attr.ib(
@@ -1654,10 +1672,12 @@ def _get_package_versions_map(self, name):
self.packages[normalized_name] = versions
except RemoteNotFetchedException as e:
if TRACE:
- print(f"failed to fetch package name: {name} from: {self.index_url}:\n{e}")
+ print(
+ f"failed to fetch package name: {name} from: {self.index_url}:\n{e}")
if not versions and TRACE:
- print(f"WARNING: package {name} not found in repo: {self.index_url}")
+ print(
+ f"WARNING: package {name} not found in repo: {self.index_url}")
return versions
@@ -1842,7 +1862,8 @@ def get(self, path_or_url, as_text=True, force=False):
if force or not os.path.exists(cached):
if TRACE_DEEP:
print(f" FILE CACHE MISS: {path_or_url}")
- content = get_file_content(path_or_url=path_or_url, as_text=as_text)
+ content = get_file_content(
+ path_or_url=path_or_url, as_text=as_text)
wmode = "w" if as_text else "wb"
with open(cached, wmode) as fo:
fo.write(content)
@@ -1864,7 +1885,8 @@ def get_file_content(path_or_url, as_text=True):
if path_or_url.startswith("https://"):
if TRACE_DEEP:
print(f"Fetching: {path_or_url}")
- _headers, content = get_remote_file_content(url=path_or_url, as_text=as_text)
+ _headers, content = get_remote_file_content(
+ url=path_or_url, as_text=as_text)
return content
elif path_or_url.startswith("file://") or (
@@ -1930,7 +1952,8 @@ def get_remote_file_content(
)
else:
- raise RemoteNotFetchedException(f"Failed HTTP request from {url} with {status}")
+ raise RemoteNotFetchedException(
+ f"Failed HTTP request from {url} with {status}")
if headers_only:
return response.headers, None
@@ -2021,7 +2044,8 @@ def get_other_dists(_package, _dist):
# if has key data we may look to improve later, but we can move on
if local_dist.has_key_metadata():
local_dist.save_about_and_notice_files(dest_dir=dest_dir)
- local_dist.fetch_license_files(dest_dir=dest_dir, use_cached_index=use_cached_index)
+ local_dist.fetch_license_files(
+ dest_dir=dest_dir, use_cached_index=use_cached_index)
continue
# lets try to get from another dist of the same local package
@@ -2033,7 +2057,8 @@ def get_other_dists(_package, _dist):
# if has key data we may look to improve later, but we can move on
if local_dist.has_key_metadata():
local_dist.save_about_and_notice_files(dest_dir=dest_dir)
- local_dist.fetch_license_files(dest_dir=dest_dir, use_cached_index=use_cached_index)
+ local_dist.fetch_license_files(
+ dest_dir=dest_dir, use_cached_index=use_cached_index)
continue
# try to get another version of the same package that is not our version
@@ -2044,7 +2069,8 @@ def get_other_dists(_package, _dist):
]
other_local_version = other_local_packages and other_local_packages[-1]
if other_local_version:
- latest_local_dists = list(other_local_version.get_distributions())
+ latest_local_dists = list(
+ other_local_version.get_distributions())
for latest_local_dist in latest_local_dists:
latest_local_dist.load_about_data(dest_dir=dest_dir)
if not latest_local_dist.has_key_metadata():
@@ -2070,7 +2096,8 @@ def get_other_dists(_package, _dist):
# if has key data we may look to improve later, but we can move on
if local_dist.has_key_metadata():
local_dist.save_about_and_notice_files(dest_dir=dest_dir)
- local_dist.fetch_license_files(dest_dir=dest_dir, use_cached_index=use_cached_index)
+ local_dist.fetch_license_files(
+ dest_dir=dest_dir, use_cached_index=use_cached_index)
continue
# try to get a latest version of the same package that is not our version
@@ -2111,7 +2138,8 @@ def get_other_dists(_package, _dist):
# if local_dist.has_key_metadata() or not local_dist.has_key_metadata():
local_dist.save_about_and_notice_files(dest_dir)
- lic_errs = local_dist.fetch_license_files(dest_dir, use_cached_index=use_cached_index)
+ lic_errs = local_dist.fetch_license_files(
+ dest_dir, use_cached_index=use_cached_index)
if not local_dist.has_key_metadata():
print(f"Unable to add essential ABOUT data for: {local_dist}")
@@ -2259,7 +2287,8 @@ def find_problems(
for dist in package.get_distributions():
dist.load_about_data(dest_dir=dest_dir)
- abpth = os.path.abspath(os.path.join(dest_dir, dist.about_filename))
+ abpth = os.path.abspath(os.path.join(
+ dest_dir, dist.about_filename))
if not dist.has_key_metadata():
print(f" Missing key ABOUT data in file://{abpth}")
if "classifiers" in dist.extra_data:
diff --git a/tests/test_ossf_scorecard.py b/tests/test_ossf_scorecard.py
index 536d8e4..61ed918 100644
--- a/tests/test_ossf_scorecard.py
+++ b/tests/test_ossf_scorecard.py
@@ -42,3 +42,19 @@ def test_get_scorecard(platform, org, repo):
# Check that the URL is valid and has the expected structure
assert data.scoring_tool_documentation_url.startswith("https://github.com/")
assert "docs/checks.md" in data.scoring_tool_documentation_url
+
+ # Check that data.checks contains valid ScorecardCheck objects
+ for check in data.checks:
+ assert hasattr(check, "check_name")
+ assert hasattr(check, "check_score")
+ assert hasattr(check, "reason")
+ assert hasattr(check, "details")
+
+ assert isinstance(check.check_name, str)
+ assert isinstance(check.check_score, str)
+ assert isinstance(check.reason, (str, type(None))) # Allow None if not provided
+ assert isinstance(check.details, (list, type(None))) # Allow None or list
+
+ # If details exist, ensure all elements are strings
+ if check.details:
+ assert all(isinstance(detail, str) for detail in check.details)