From 9c57f340d22d8891a5614a93553b20d75e2f3136 Mon Sep 17 00:00:00 2001 From: Chin Yeung Li Date: Tue, 20 Aug 2024 16:46:20 +0800 Subject: [PATCH 01/29] Update link references of ownership from nexB to aboutcode-org Signed-off-by: Chin Yeung Li --- Makefile | 4 +- NOTICE | 2 +- configure | 2 +- configure.bat | 2 +- docs/source/conf.py | 2 +- docs/source/contribute/contrib_doc.rst | 2 +- docs/source/skeleton-usage.rst | 2 +- etc/scripts/check_thirdparty.py | 5 +- etc/scripts/fetch_thirdparty.py | 19 ++++-- etc/scripts/gen_requirements.py | 2 +- etc/scripts/gen_requirements_dev.py | 2 +- etc/scripts/utils_dejacode.py | 11 ++-- etc/scripts/utils_requirements.py | 11 ++-- etc/scripts/utils_thirdparty.py | 89 +++++++++++++++++--------- setup.cfg | 2 +- tests/test_skeleton_codestyle.py | 2 +- 16 files changed, 100 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index cc36c35557d..94451b33248 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. # @@ -35,7 +35,7 @@ check: @echo "-> Run pycodestyle (PEP8) validation" @${ACTIVATE} pycodestyle --max-line-length=100 --exclude=.eggs,venv,lib,thirdparty,docs,migrations,settings.py,.cache . @echo "-> Run isort imports ordering validation" - @${ACTIVATE} isort --sl --check-only -l 100 setup.py src tests . + @${ACTIVATE} isort --sl --check-only -l 100 setup.py src tests . @echo "-> Run black validation" @${ACTIVATE} black --check --check -l 100 src tests setup.py diff --git a/NOTICE b/NOTICE index 65936b2bfd6..cbdaef7952a 100644 --- a/NOTICE +++ b/NOTICE @@ -2,7 +2,7 @@ # Copyright (c) nexB Inc. and others. # SPDX-License-Identifier: Apache-2.0 # -# Visit https://aboutcode.org and https://github.com/nexB/ for support and download. +# Visit https://aboutcode.org and https://github.com/aboutcode-org/ for support and download. # ScanCode is a trademark of nexB Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/configure b/configure index 926a894eb66..22d92885864 100755 --- a/configure +++ b/configure @@ -3,7 +3,7 @@ # Copyright (c) nexB Inc. and others. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # See http://www.apache.org/licenses/LICENSE-2.0 for the license text. -# See https://github.com/nexB/ for support or download. +# See https://github.com/aboutcode-org/ for support or download. # See https://aboutcode.org for more information about nexB OSS projects. # diff --git a/configure.bat b/configure.bat index 5e95b3110f7..5b9a9d68528 100644 --- a/configure.bat +++ b/configure.bat @@ -4,7 +4,7 @@ @rem Copyright (c) nexB Inc. and others. All rights reserved. @rem SPDX-License-Identifier: Apache-2.0 @rem See http://www.apache.org/licenses/LICENSE-2.0 for the license text. -@rem See https://github.com/nexB/ for support or download. +@rem See https://github.com/aboutcode-org/ for support or download. @rem See https://aboutcode.org for more information about nexB OSS projects. diff --git a/docs/source/conf.py b/docs/source/conf.py index 7771ff094f4..8c88fa2c999 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -43,7 +43,7 @@ # This points to aboutcode.readthedocs.io # In case of "undefined label" ERRORS check docs on intersphinx to troubleshoot -# Link was created at commit - https://github.com/nexB/aboutcode/commit/faea9fcf3248f8f198844fe34d43833224ac4a83 +# Link was created at commit - https://github.com/aboutcode-org/aboutcode/commit/faea9fcf3248f8f198844fe34d43833224ac4a83 intersphinx_mapping = { "aboutcode": ("https://aboutcode.readthedocs.io/en/latest/", None), diff --git a/docs/source/contribute/contrib_doc.rst b/docs/source/contribute/contrib_doc.rst index 13882e1082e..5640db264be 100644 --- a/docs/source/contribute/contrib_doc.rst +++ b/docs/source/contribute/contrib_doc.rst @@ -12,7 +12,7 @@ To get started, create or identify a working directory on your local machine. Open that directory and execute the following command in a terminal session:: - git clone https://github.com/nexB/skeleton.git + git clone https://github.com/aboutcode-org/skeleton.git That will create an ``/skeleton`` directory in your working directory. Now you can install the dependencies in a virtualenv:: diff --git a/docs/source/skeleton-usage.rst b/docs/source/skeleton-usage.rst index cde23dcdeb2..6cb4cc5f4b5 100644 --- a/docs/source/skeleton-usage.rst +++ b/docs/source/skeleton-usage.rst @@ -118,7 +118,7 @@ corrected. You can check to see if your corrections are valid by running: Once the wheels are collected and the ABOUT files are generated and correct, upload them to thirdparty.aboutcode.org/pypi by placing the wheels and ABOUT files from the thirdparty directory to the pypi directory at -https://github.com/nexB/thirdparty-packages +https://github.com/aboutcode-org/thirdparty-packages Usage after project initialization diff --git a/etc/scripts/check_thirdparty.py b/etc/scripts/check_thirdparty.py index b052f25b278..2daded948fa 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 eedf05c672f..3f9ff527a1e 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 07e26f77126..2b65ae807ef 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 12cc06d385a..5db1c48ed73 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 c42e6c9313b..652252d48ed 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 0fc25a35c8b..1c502390f2c 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 addf8e5e106..46dc7289351 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/setup.cfg b/setup.cfg index a8e20c5d427..ef7d369b42a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ license = Apache-2.0 description = skeleton long_description = file:README.rst long_description_content_type = text/x-rst -url = https://github.com/nexB/skeleton +url = https://github.com/aboutcode-org/skeleton author = nexB. Inc. and others author_email = info@aboutcode.org diff --git a/tests/test_skeleton_codestyle.py b/tests/test_skeleton_codestyle.py index 2eb6e558fcb..b4ce8c167d8 100644 --- a/tests/test_skeleton_codestyle.py +++ b/tests/test_skeleton_codestyle.py @@ -3,7 +3,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. # From 206fd48f5b354454e067dc33a854a898b6247b00 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 29 Oct 2024 16:35:55 +0530 Subject: [PATCH 02/29] Add new licenses and updates Signed-off-by: Ayan Sinha Mahapatra --- .../data/licenses/djangosnippets-tos.LICENSE | 23 +++++++++++++ .../data/licenses/freetos-mit.LICENSE | 32 +++++++++++++++++++ .../data/licenses/lanl-bsd-3-variant.LICENSE | 24 ++++++++++++++ .../data/licenses/unicode-v3.LICENSE | 1 + 4 files changed, 80 insertions(+) create mode 100644 src/licensedcode/data/licenses/djangosnippets-tos.LICENSE create mode 100644 src/licensedcode/data/licenses/freetos-mit.LICENSE create mode 100644 src/licensedcode/data/licenses/lanl-bsd-3-variant.LICENSE diff --git a/src/licensedcode/data/licenses/djangosnippets-tos.LICENSE b/src/licensedcode/data/licenses/djangosnippets-tos.LICENSE new file mode 100644 index 00000000000..a676f0943ea --- /dev/null +++ b/src/licensedcode/data/licenses/djangosnippets-tos.LICENSE @@ -0,0 +1,23 @@ +--- +key: djangosnippets-tos +short_name: Djangosnippets TOS +name: Djangosnippets Terms of Service +category: CLA +owner: Djangosnippets +homepage_url: https://djangosnippets.org/about/tos/ +spdx_license_key: LicenseRef-scancode-djangosnippets-tos +--- + +Terms of Service + +We hate legal-speak as much as anybody, but on a site which is geared toward sharing code there has to be at least a little bit of it, so here goes: + +By creating an account here you agree to three things: + +1. That you will only post code which you wrote yourself and that you have the legal right to release under these terms. + +2. That you grant any third party who sees the code you post a royalty-free, non-exclusive license to copy and distribute that code and to make and distribute derivative works based on that code. You may include license terms in snippets you post, if you wish to use a particular license (such as the BSD license or GNU GPL), but that license must permit royalty-free copying, distribution and modification of the code to which it is applied. + +3. That if you post code of which you are not the author or for which you do not have the legal right to distribute according to these terms, you will indemnify and hold harmless the operators of this site and any third parties who are exposed to liability as a result of your actions. + +If you can't legally agree to these terms, or don't want to, you cannot create an account here. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/freetos-mit.LICENSE b/src/licensedcode/data/licenses/freetos-mit.LICENSE new file mode 100644 index 00000000000..ea6af97c682 --- /dev/null +++ b/src/licensedcode/data/licenses/freetos-mit.LICENSE @@ -0,0 +1,32 @@ +--- +key: freetos-mit +short_name: FreeRTOS MIT +name: FreeRTOS MIT +category: Permissive +owner: FreeRTOS +homepage_url: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.0.0/FreeRTOS/Source/list.c +spdx_license_key: LicenseRef-scancode-freetos-mit +text_urls: + - https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.0.0/FreeRTOS/Source/list.c +other_urls: + - http://www.FreeRTOS.org + - http://aws.amazon.com/freertos +--- + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. If you wish to use our Amazon +FreeRTOS name, please do so in a fair use way that does not cause confusion. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/lanl-bsd-3-variant.LICENSE b/src/licensedcode/data/licenses/lanl-bsd-3-variant.LICENSE new file mode 100644 index 00000000000..956ee2caa40 --- /dev/null +++ b/src/licensedcode/data/licenses/lanl-bsd-3-variant.LICENSE @@ -0,0 +1,24 @@ +--- +key: lanl-bsd-3-variant +short_name: LANL BSD-3 Variant +name: Los Alamos National Labs BSD-3 Variant +category: Permissive +owner: LANL +homepage_url: https://opensource.org/license/los-alamos-national-labs-bsd-3-variant +spdx_license_key: LicenseRef-scancode-lanl-bsd-3-variant +osi_url: https://opensource.org/license/los-alamos-national-labs-bsd-3-variant +ignorable_copyrights: + - Copyright XXXX. Los Alamos National Security, LLC. +ignorable_holders: + - XXXX. Los Alamos National Security, LLC. +--- + +Copyright XXXX. Los Alamos National Security, LLC. This software was produced under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National Laboratory (LANL), which is operated by Los Alamos National Security, LLC for the U.S. Department of Energy. The U.S. Government has rights to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce derivative works, such modified software should be clearly marked, so as not to confuse it with the version available from LANL. + +Additionally, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + Neither the name of Los Alamos National Security, LLC, Los Alamos National Laboratory, LANL, the U.S. Government, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY LOS ALAMOS NATIONAL SECURITY, LLC AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/unicode-v3.LICENSE b/src/licensedcode/data/licenses/unicode-v3.LICENSE index b21432f5c8c..78acd2c67d4 100644 --- a/src/licensedcode/data/licenses/unicode-v3.LICENSE +++ b/src/licensedcode/data/licenses/unicode-v3.LICENSE @@ -8,6 +8,7 @@ homepage_url: https://www.unicode.org/license.txt spdx_license_key: Unicode-3.0 other_spdx_license_keys: - LicenseRef-scancode-unicode-v3 +osi_url: https://opensource.org/license/unicode-license-v3 --- UNICODE LICENSE V3 From 41bc945aef74b0e6db58ad0c5e467a93a52e76a1 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 5 Nov 2024 19:42:33 +0530 Subject: [PATCH 03/29] Add fixes to license metadata Signed-off-by: Ayan Sinha Mahapatra --- .../{freetos-mit.LICENSE => freertos-mit.LICENSE} | 9 ++------- src/licensedcode/data/licenses/punycode.LICENSE | 2 ++ 2 files changed, 4 insertions(+), 7 deletions(-) rename src/licensedcode/data/licenses/{freetos-mit.LICENSE => freertos-mit.LICENSE} (84%) diff --git a/src/licensedcode/data/licenses/freetos-mit.LICENSE b/src/licensedcode/data/licenses/freertos-mit.LICENSE similarity index 84% rename from src/licensedcode/data/licenses/freetos-mit.LICENSE rename to src/licensedcode/data/licenses/freertos-mit.LICENSE index ea6af97c682..b34fec848b6 100644 --- a/src/licensedcode/data/licenses/freetos-mit.LICENSE +++ b/src/licensedcode/data/licenses/freertos-mit.LICENSE @@ -1,16 +1,11 @@ --- -key: freetos-mit +key: freertos-mit short_name: FreeRTOS MIT name: FreeRTOS MIT category: Permissive owner: FreeRTOS homepage_url: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.0.0/FreeRTOS/Source/list.c -spdx_license_key: LicenseRef-scancode-freetos-mit -text_urls: - - https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.0.0/FreeRTOS/Source/list.c -other_urls: - - http://www.FreeRTOS.org - - http://aws.amazon.com/freertos +spdx_license_key: LicenseRef-scancode-freertos-mit --- Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/src/licensedcode/data/licenses/punycode.LICENSE b/src/licensedcode/data/licenses/punycode.LICENSE index 329f4d5466d..b083744dcef 100644 --- a/src/licensedcode/data/licenses/punycode.LICENSE +++ b/src/licensedcode/data/licenses/punycode.LICENSE @@ -6,6 +6,8 @@ category: Permissive owner: nicemice homepage_url: https://git.savannah.gnu.org/gitweb/?p=libidn.git;a=blob;f=lib/punycode.c;h=14d70152b9c5723778af174ff6027cc3742b749e;hb=HEAD#l54 spdx_license_key: LicenseRef-scancode-punycode +text_urls: + - https://datatracker.ietf.org/doc/html/rfc3492#page-22 --- Disclaimer and license: Regarding this entire document or any From d7fc4cc9cf695b17a40896c960f5635953202ea6 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Thu, 14 Nov 2024 17:22:19 +0530 Subject: [PATCH 04/29] Fix package resource assign bug for jar manifests Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/maven.py | 11 +- src/packagedcode/models.py | 6 + ...ackson-dataformat-xml-2.13.5-expected.json | 4 +- .../spring-web-5.3.20-jar-expected.json | 321 ++++++++++++++++++ .../spring-web-5.3.20.jar | Bin 0 -> 180 bytes .../META-INF/MANIFEST.MF | 6 + .../META-INF/notice.txt | 6 + .../extracted-jar/hsqldb-2.4.0-expected.json | 16 +- tests/packagedcode/test_maven.py | 9 +- 9 files changed, 369 insertions(+), 10 deletions(-) create mode 100644 tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar-expected.json create mode 100644 tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar/spring-web-5.3.20.jar create mode 100644 tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/MANIFEST.MF create mode 100644 tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt diff --git a/src/packagedcode/maven.py b/src/packagedcode/maven.py index c2ad164a199..c3910f213b6 100644 --- a/src/packagedcode/maven.py +++ b/src/packagedcode/maven.py @@ -68,6 +68,9 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ yield from models.DatafileHandler.assemble(package_data, resource, codebase) return + if not package_data.purl: + return + datafile_path = resource.path # This order is important as we want pom.xml to be used for package @@ -116,11 +119,11 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ parent_resource=parent_resource, ) elif manifests and not pom_xmls: - yield from JavaJarManifestHandlerMixin.assemble(package_data, resource, codebase) + yield from JavaJarManifestHandlerMixin.assemble(package_data, resource, codebase, package_adder) elif pom_xmls and not manifests: - yield from MavenPomXmlHandlerMixin.assemble(package_data, resource, codebase) + yield from MavenPomXmlHandlerMixin.assemble(package_data, resource, codebase, package_adder) else: - yield from models.DatafileHandler.assemble(package_data, resource, codebase) + yield from models.DatafileHandler.assemble(package_data, resource, codebase, package_adder) class JavaJarManifestHandler(MavenBasePackageHandler): @@ -149,7 +152,7 @@ def assign_package_to_resources(cls, package, resource, codebase, package_adder) # we want to root of the jar, two levels up parent = resource.parent(codebase) if parent: - parent = resource.parent(codebase) + parent = parent.parent(codebase) if parent: models.DatafileHandler.assign_package_to_resources( package, diff --git a/src/packagedcode/models.py b/src/packagedcode/models.py index 2224c2d5121..45a2f6d4de6 100644 --- a/src/packagedcode/models.py +++ b/src/packagedcode/models.py @@ -1199,6 +1199,12 @@ def assign_package_to_resources(cls, package, resource, codebase, package_adder= # NOTE: we do not attach files to the Package level. Instead we # update `for_packages` of a codebase resource. package_uid = package.package_uid + if resource.path.endswith("-extract"): + archive_resource_path = resource.path.removesuffix("-extract") + archive_resource = codebase.get_resource(archive_resource_path) + if archive_resource: + package_adder(package_uid, archive_resource, codebase) + if resource and package_uid: package_adder(package_uid, resource, codebase) for res in resource.walk(codebase): diff --git a/tests/packagedcode/data/maven_misc/assemble/jackson-dataformat-xml-2.13.5-expected.json b/tests/packagedcode/data/maven_misc/assemble/jackson-dataformat-xml-2.13.5-expected.json index 969783dfcf1..aacbb9fa2e7 100644 --- a/tests/packagedcode/data/maven_misc/assemble/jackson-dataformat-xml-2.13.5-expected.json +++ b/tests/packagedcode/data/maven_misc/assemble/jackson-dataformat-xml-2.13.5-expected.json @@ -188,7 +188,9 @@ "path": "jackson-dataformat-xml-2.13.5", "type": "directory", "package_data": [], - "for_packages": [], + "for_packages": [ + "pkg:jar/Jackson-dataformat-XML@2.13.5?uuid=fixed-uid-done-for-testing-5642512d1758" + ], "detected_license_expression": null, "detected_license_expression_spdx": null, "license_detections": [], diff --git a/tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar-expected.json b/tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar-expected.json new file mode 100644 index 00000000000..a60e601249c --- /dev/null +++ b/tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar-expected.json @@ -0,0 +1,321 @@ +{ + "packages": [ + { + "type": "jar", + "namespace": null, + "name": "spring-web", + "version": "5.3.20", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt", + "start_line": 4, + "end_line": 6, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 27, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "apache-2.0_701.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/apache-2.0_701.RULE" + } + ], + "detection_log": [], + "identifier": "apache_2_0-dda7c7b6-8825-2c52-d55b-46f66d469baa" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "package_uid": "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/MANIFEST.MF" + ], + "datasource_ids": [ + "java_jar_manifest" + ], + "purl": "pkg:jar/spring-web@5.3.20" + } + ], + "dependencies": [], + "license_detections": [ + { + "identifier": "apache_2_0-dda7c7b6-8825-2c52-d55b-46f66d469baa", + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "detection_count": 2, + "detection_log": [], + "reference_matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt", + "start_line": 4, + "end_line": 6, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 27, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "apache-2.0_701.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/apache-2.0_701.RULE" + } + ] + } + ], + "files": [ + { + "path": "spring-web-5.3.20-jar", + "type": "directory", + "package_data": [], + "for_packages": [], + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "spring-web-5.3.20-jar/spring-web-5.3.20.jar", + "type": "file", + "package_data": [ + { + "type": "jar", + "namespace": null, + "name": null, + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "java_jar", + "purl": null + } + ], + "for_packages": [ + "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/MANIFEST.MF", + "type": "file", + "package_data": [ + { + "type": "jar", + "namespace": null, + "name": "spring-web", + "version": "5.3.20", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": "", + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt", + "start_line": 4, + "end_line": 6, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 27, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "apache-2.0_701.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/apache-2.0_701.RULE" + } + ], + "detection_log": [], + "identifier": "apache_2_0-dda7c7b6-8825-2c52-d55b-46f66d469baa" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "java_jar_manifest", + "purl": "pkg:jar/spring-web@5.3.20" + } + ], + "for_packages": [ + "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt", + "type": "file", + "package_data": [], + "for_packages": [ + "pkg:jar/spring-web@5.3.20?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "detected_license_expression": "apache-2.0", + "detected_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "spring-web-5.3.20-jar/spring-web-5.3.20.jar-extract/META-INF/notice.txt", + "start_line": 4, + "end_line": 6, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 27, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "apache-2.0_701.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/apache-2.0_701.RULE" + } + ], + "detection_log": [], + "identifier": "apache_2_0-dda7c7b6-8825-2c52-d55b-46f66d469baa" + } + ], + "license_clues": [], + "percentage_of_license_text": 71.05, + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar/spring-web-5.3.20.jar b/tests/packagedcode/data/maven_misc/assemble/spring-web-5.3.20-jar/spring-web-5.3.20.jar new file mode 100644 index 0000000000000000000000000000000000000000..46ba8b458e9b899fb130668d12db60d1eea34ddb GIT binary patch literal 180 zcmWIWW@Zs#00E=kyhtzuN^mkLF!;KLIO=-(x#@?7@G`Lfcww3j!=)A642&! Date: Wed, 20 Nov 2024 21:44:24 +0530 Subject: [PATCH 05/29] Add new licenses added to dejacode Added by @DennisClark, thanks to @armijnhemel and @pombredanne for reporting these too. Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/3992 Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/3991 Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/3990 Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/3993 Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/3973 Signed-off-by: Ayan Sinha Mahapatra --- .../data/licenses/autosar-proprietary.LICENSE | 30 + .../licenses/rocket-master-terms-2022.LICENSE | 773 ++++++++++++++++++ .../data/licenses/salesforcesans-font.LICENSE | 120 +++ .../data/licenses/snowplow-cla-1.0.LICENSE | 62 ++ .../data/licenses/snowplow-lula-1.0.LICENSE | 68 ++ .../snowplow-person-academic-1.0.LICENSE | 67 ++ 6 files changed, 1120 insertions(+) create mode 100644 src/licensedcode/data/licenses/autosar-proprietary.LICENSE create mode 100644 src/licensedcode/data/licenses/rocket-master-terms-2022.LICENSE create mode 100644 src/licensedcode/data/licenses/salesforcesans-font.LICENSE create mode 100644 src/licensedcode/data/licenses/snowplow-cla-1.0.LICENSE create mode 100644 src/licensedcode/data/licenses/snowplow-lula-1.0.LICENSE create mode 100644 src/licensedcode/data/licenses/snowplow-person-academic-1.0.LICENSE diff --git a/src/licensedcode/data/licenses/autosar-proprietary.LICENSE b/src/licensedcode/data/licenses/autosar-proprietary.LICENSE new file mode 100644 index 00000000000..bca6dbeb9b8 --- /dev/null +++ b/src/licensedcode/data/licenses/autosar-proprietary.LICENSE @@ -0,0 +1,30 @@ +--- +key: autosar-proprietary +short_name: AUTOSAR Proprietary Notice +name: AUTOSAR Proprietary Notice +category: Proprietary Free +owner: AUTOSAR +spdx_license_key: LicenseRef-scancode-autosar-proprietary +text_urls: + - https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_PRS_SOMEIPProtocol.pdf + - https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol.pdf +--- + +Disclaimer +This work (specification and/or software implementation) and the material contained in +it, as released by AUTOSAR, is for the purpose of information only. AUTOSAR and the +companies that have contributed to it shall not be liable for any use of the work. + +The material contained in this work is protected by copyright and other types of intel- +lectual property rights. The commercial exploitation of the material contained in this +work requires a license to such intellectual property rights. + +This work may be utilized or reproduced without any modification, in any form or by +any means, for informational purposes only. For any other purpose, no part of the work +may be utilized or reproduced, in any form or by any means, without permission in +writing from the publisher. + +The work has been developed for automotive applications only. It has neither been +developed, nor tested for non-automotive applications. + +The word AUTOSAR and the AUTOSAR logo are registered trademarks. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/rocket-master-terms-2022.LICENSE b/src/licensedcode/data/licenses/rocket-master-terms-2022.LICENSE new file mode 100644 index 00000000000..7a069c4af9d --- /dev/null +++ b/src/licensedcode/data/licenses/rocket-master-terms-2022.LICENSE @@ -0,0 +1,773 @@ +--- +key: rocket-master-terms-2022 +short_name: Rocket Software Master Terms 2022 +name: Rocket Software Master Terms and Conditions 2022 +category: Commercial +owner: Rocket Software +homepage_url: https://github.com/RocketSoftware/jcl-projcl-vscode-ext/blob/master/LICENSE.txt +spdx_license_key: LicenseRef-scancode-rocket-master-terms-2022 +ignorable_copyrights: + - (c) Assumption of Defense + - (c) Force Majeure +ignorable_holders: + - Assumption of Defense + - Force Majeure +--- + +Rocket Software + +Master Terms and Conditions + +Rocket Software, Inc. or its subsidiary designated on an Order Form ("Rocket") +provides software Products and related Services according to these Software +License and Services Terms ("Terms"). By executing an Order Form dated on or +after the date of these Terms, Customer agrees, for itself and its majority +owned subsidiaries, these Terms apply to the first Order Form Customer executes +(together, the "Agreement") each Order Form thereafter, Customer's rights and +obligations, and previously purchased Products and Services. Each Order Form is +a separate contract incorporating these Terms and are the entire terms governing +Customer's purchase of Products and/or Services. The parties agree that they may +do business electronically, including contract formation, order placement and +acceptance. An order Customer places and Rocket accepts on any Rocket website +will create fully enforceable obligations subject to these Terms. + +A. GENERAL TERMS + +1. INTELLECTUAL PROPERTY OWNERSHIP + +Rocket, its affiliates or licensors own and retain all right, title and interest +in all Intellectual Property in Products, Services, Deliverables, Documentation, +(except as otherwise specified herein), developments, research data, designs, +layout, methodologies, processes and procedures, models, formulae, documents, +drawings, plans, specifications and other Rocket information, proprietary +materials and all derivative works. To the extent that any right, title or +interest in or to any Rocket's Intellectual Property may not automatically vest +in Rocket by operation of law, Customer irrevocably transfers, assigns and +conveys all right, title, and interest therein to Rocket. At Rocket's request +and expense Customer will promptly take any action and execute any documents +necessary to vest full title in Rocket or its licensor. + +2. CONFIDENTIALITY + +(a) Confidential Information. Whether or not disclosed orally or marked as +confidential, Confidential Information includes the Agreement; Order Forms, +Products, Deliverables, and Services; either party's non-public data or +personally identifiable information regarding employees or customer(s) residing +on the party's computer systems; Intellectual Property, and Rocket's proposals, +specifications, manuals, product roadmaps, financial data, pricing, and results +of benchmark tests. Confidential Information does not include information that +is (i) publicly available without breach of the Agreement; (ii) reasonably shown +to Disclosing Party's satisfaction to have been known by Receiving Party prior +to disclosure or independently developed by Receiving Party subsequent to +disclosure without breach of these Terms; or (iii) obtained by Receiving Party +from a third party without confidentiality obligation. Products are not deemed +to be placed in the public domain by Rocket. Receiving Party will promptly +notify Disclosing Party if it is compelled by a court or legal process to +disclose Confidential Information and will take any reasonable action requested +by Disclosing Party to maintain the confidentiality of the Confidential +Information. + +(b) Non-disclosure. Customer will use best efforts to prevent disclosure to +Rocket of any personally identifiable information (PII) regarding Customer's +employees or customer(s). Customer is solely responsible for complying with any +requirements regarding PII disclosed to Rocket, other than Rocket's +confidentiality obligations hereunder. Receiving Party will use Disclosing +Party's Confidential Information solely to perform its obligations under the +Agreement. Receiving Party will take commercially reasonable steps to safeguard +Disclosing Party's Confidential Information, including no less than the steps +taken to protect its own Confidential Information. Receiving Party must not +disclose Disclosing Party's Confidential Information except to its employees +bound by written confidentiality obligations, or Affiliates under a duty of +confidentiality, no less restrictive than these Terms. Receiving Party must +promptly notify Disclosing Party in writing of unauthorized use or disclosure of +Confidential Information. Receiving Party, at its expense, must take all +reasonable action to recover Confidential Information and prevent further +unauthorized use or disclosure, including action for seizure and injunctive +relief. If Receiving Party fails to do so in a timely manner, Disclosing Party +may take reasonable action to do so at Receiving Party's expense, and Receiving +Party must reasonably cooperate. + +3. INTELLECTUAL PROPERTY INDEMNIFICATION + +(a) By Rocket. + +(i) Rocket will defend, at its expense, a third party legal action, suit or +proceeding against Customer ("Claim") to the extent that a Product, or a +Deliverable that is a Product proprietary derivative work, as delivered by +Rocket to Customer ("Indemnified Product") directly infringes a valid U.S. +patent or copyright. Rocket will indemnify Customer for any judgment finally +awarded against Customer or settlement agreed by Rocket for such Claim to the +extent of the Indemnified Product's infringement, provided (1) Customer notifies +Rocket promptly in writing of the Claim, (2) Rocket has sole control over the +defense or settlement, and (3) Customer fully cooperates with Rocket, providing +all documents and information in Customer's possession relevant to the Claim, +and Customer makes personnel available to testify or consult with Rocket. + +(ii) If an Indemnified Product becomes, or in Rocket's opinion is likely to +become subject to a Claim, Rocket may, at its option and expense, (1) acquire +the right for Customer to continue using the Indemnified Product, (2) replace or +modify the Indemnified Product or create a workaround so that the Indemnified +Product is functionally equivalent and non-infringing, or (3) terminate the +License for the Indemnified Product and give Customer a credit for the Product +Fee paid by Customer for the infringing part of the Indemnified Product, less a +reasonable allowance for the time Customer used the Indemnified Product. + +(iii) Rocket is not obligated or liable for a Claim due to: (1) use of an +Indemnified Product not according to the Agreement and Documentation, (2) +modification of an Indemnified Product made by anyone other than Rocket, or +modification made by Rocket for non-standard features or functionality for +Customer or according to Customer's directions, (3) any products, equipment, +software, or data not supplied by Rocket, (4) use of an Indemnified Product +combined with any other products, equipment, software, or data not supplied by +Rocket if infringement would not occur without the combination, (5) a release +of Indemnified Product other than the most current release available or +Customer's failure to install a revision, update or release that would have +eliminated the infringement, (6) Customer's designs, instructions, plans or +specifications, or (7) use of an Indemnified Product combined with a Customer or +third party use, process or method if infringement would not occur without the +combination. + +(b) By Customer. + +(i) Customer will defend, at its expense, a third party claim against Rocket (1) +that any product, information, data or material provided by Customer infringes +another party's intellectual property rights, other than a Claim for which +Rocket is responsible according to Section A3(a) above, or (2) arising from +Customer's or its Affiliates' failure to comply with the License or +Confidentiality terms of the Agreement. + +(ii) Customer will indemnify Rocket for any damages, or amounts agreed as +settlement, for the claim, provided (1) Rocket notifies Customer promptly in +writing of the claim, (2) Customer has sole control over the defense or +settlement, and (3) Rocket cooperates with Customer, providing all documents and +information in Rocket's possession relevant to the claim, and Rocket makes +personnel available to testify or consult with Customer as reasonably needed. + +(c) Assumption of Defense. If a party fails to defend or settle a claim +according to this Section A3 in a timely manner, the other party may assume +defense of the claim at the indemnifying party's expense, and the indemnifying +party will reasonably cooperate. Neither party may make an admission of fault on +behalf of the other party, or agree to the settlement of a claim binding the +other party that does not contain a full release of liability for the other +party, without written consent. (d) Limitation. THIS SECTION A3 DESCRIBES EACH +PARTY'S SOLE LIABILITY AND THE OTHER PARTY'S SOLE REMEDY FOR INTELLECTUAL +PROPERTY INFRINGEMENT INDEMNIFICATION. + +(d) Professional Services Indemnity. Each party will defend, at their expense, +any action brought against the other party for bodily injury, death, or tangible +property damage to the extent caused by the gross negligence or willful +misconduct of the defending party relating to a Professional Services +engagement. The defending party will indemnify the other party for and pay +damages finally awarded in such action, or agreed as a settlement by the +indemnifying party, if (a) the other party promptly notifies the indemnifying +party in writing of the claim, (b) the indemnifying party has sole control over +the defense or settlement, and (c) the other party cooperates in the +indemnifying party's defense or settlement. If a party with an indemnification +obligation fails to defend or settle a claim in a timely manner, the other party +may assume the defense at the obligated party's expense, and the obligated party +will reasonably cooperate. Neither party may, without the other party's written +consent, agree to a settlement that: (a) binds the other party, (b) does not +contain a full release of the other party, or (c) admits fault on behalf of the +other party. THIS SECTION A3(d) DESCRIBES EACH PARTY'S SOLE LIABILITY AND THE +OTHER PARTY'S SOLE REMEDY FOR PROFESSIONAL SERVICES INDEMNIFICATION. + +4. LIMITATION OF LIABILITY + +(a) ROCKET, ITS AFFILIATES AND LICENSORS WILL NOT BE LIABLE FOR (i) ANY +CONSEQUENTIAL, INDIRECT, SPECIAL, PUNITIVE OR INCIDENTAL DAMAGES, (ii) ANY +INTERRUPTION OF BUSINESS OR OPERATIONS, COST OF COVER, GOODWILL, TOLL FRAUD, OR +LOSS OF DATA, PROFITS, OR REVENUE, OR FAILURE OF A REMEDY TO ACHIEVE ITS +ESSENTIAL PURPOSE. + +(b) EXCEPT FOR A CLAIM FOR INFRINGEMENT UNDER SECTION A3, DEATH OR BODILY INJURY +CLAIMS, TANGIBLE PROPERTY DAMAGE, WILLFUL MISCONDUCT, OR FRAUD, ROCKET, ITS +AFFILIATES AND LICENSORS WILL NOT BE LIABLE FOR ANY DAMAGES THAT EXCEED THE +AMOUNT CUSTOMER PAID IN THE PRECEDING 12 MONTHS FOR THE PRODUCT OR SERVICE THAT +GAVE RISE TO THE CLAIM. + +(c) THE LIMITATIONS IN THIS SECTION A4 WILL APPLY TO ANY DAMAGES, HOWEVER +CAUSED, UNDER ANY THEORY OF LIABLITY, WHETHER FOR BREACH OF CONTRACT, TORT, +MISREPRESENTATION, NEGLIGENCE, THE USE OR PERFORMANCE OF A PRODUCT OR SERVICE, +OR OTHERWISE, AND REGARDLESS OF WHETHER THE DAMAGES WERE FORESEEABLE OR +UNFORSEEABLE. ROCKET WILL NOT BE LIABLE FOR ANY CLAIM BROUGHT MORE THAN 12 +MONTHS AFTER CUSTOMER BECAME AWARE OF THE ISSUE GIVING RISE TO THE CLAIM. +ROCKET'S FAILURE TO EXERCISE A RIGHT OR REMEDY IS NOT A WAIVER. + +5. DISPUTE RESOLUTION + +The parties will attempt in good faith to resolve any controversy or claim +promptly through business discussions and will, upon written request, escalate a +dispute to executive management for resolution. If the parties fail to resolve +the dispute within 30 days of written request, or any longer period agreed in +writing, the parties may pursue the remedies to which they are entitled. This +clause will not restrict either party's right to seek injunctive relief. + +6. INJUNCTIVE RELIEF + +Customer's failure to comply with the License or Confidentiality terms of the +Agreement would result in irreparable harm to Rocket that may be intangible but +real and is incapable of complete remedy by award of damages. Customer agrees +(a) Rocket has the right to an injunction or other court order and may proceed +directly to court to specifically enforce Customer's obligations, (b) no finding +of irreparable harm or other condition to injunctive relief is required, (c) an +order may be entered to compel Customer to act or refrain from acting or +threatened action, and (d) if an injunction is granted, Customer will pay +Rocket's reasonable expenses and attorney fees, in addition to any other relief +granted. Rocket shall have the right to pursue all remedies at law and in equity +for such a breach. + +7. MISCELLANEOUS + +(a) Agreement. The Agreement supersedes all other oral or written terms, +proposals or representations in effect between the parties regarding Rocket +Products and Services. Any terms in a subsequent or contemporaneous Order Form +that are inconsistent with these Terms will control for that Order Form only, +and the General Terms may only be modified by a written amendment signed by both +parties. Inconsistent terms of Customer's purchase order are excluded regardless +of Rocket accepting the purchase order for payment purposes. If any Agreement +term is illegal, invalid, or unenforceable, the other terms remain in full force +and effect and any term that is intended to survive the Agreement termination +will survive. + +(b) Assignment. Customer may not assign the Agreement, an Order Form, or any of +its obligations, rights or remedies, in whole or in part, without Rocket's prior +written approval in its sole discretion. + +(c) Force Majeure. Neither party is liable for delay or failing to perform its +obligations due to a cause beyond its reasonable control and without fault or +negligence, except Customer's failure to perform its payment obligations. + +(d) Governing Law, Jurisdiction and Region-Specific Terms Massachusetts laws +govern the Agreement, the parties' performance, rights and obligations, +excluding conflict of law principles that would apply the law of any other +jurisdiction. Each party waives the right to jury trial for a claim in law or +equity. The United Nations Convention on Contracts for the International Sale of +Goods and the Uniform Computer Information Transaction Act, as adopted, do not +apply. US, North and South America, and Rest of World. For customers located in +the United States, North and South America, and any other jurisdiction not +covered by the region-specific terms below (Rest of World), the following terms +apply: Governing Law; This Agreement is governed by the laws of the Commonwealth +of Massachusetts and the United States, without regard to choice or conflict of +law rules thereof. U.S. Government Use. The Rocket Services are based upon +commercial computer software. If the user or licensee of an Rocket Service is an +agency, department or other entity of the United States Government, the use, +duplication, reproduction, release, modification, disclosure or transfer of the +Rocket Service, or any related documentation of any kind, including technical +data and manuals, is restricted by a license agreement or by this Agreement in +accordance with Federal Acquisition Regulations 12.211 (Technical Data) and +12.212 (Computer Software) for civilian purposes and Defense Federal Acquisition +Regulation Supplement 227.7202-3 (Rights in Commercial Computer Software or +Computer Software Documentation). The Rocket Services were developed fully at +private expense. All other use is prohibited. If greater rights are needed, a +mutually acceptable written amendment specifically conveying these rights must +be included as part of this Agreement. General. The Uniform Computer +Information Transactions Act (UCITA) do not apply to this Agreement regardless +of when or where adopted. + +UK, IE, Middle East, Africa, Russia, and India. For customers located in the +Republic of Ireland, the United Kingdom, British Crown Dependencies, British +Overseas Territories, Middle East, Africa, Russia, and India the following terms +apply: Governing Law; Jurisdiction and Venue. This Agreement is governed by the +laws of England and Wales and the parties submit to the exclusive jurisdiction +and venue of courts located in England. + +Germany, Austria, and Switzerland ("DACH"). For customers located in DACH, the +following terms apply: Governing Law; Jurisdiction and Venue. This Agreement is +governed by the laws of Germany and the parties submit to the exclusive +jurisdiction and venue of courts located in Germany. Clarification on Liability +Cap under Section A.4(Limitation of Liability). THE PARTIES AGREE THAT THE +LIABILITY CAP AT SECTION A.4 APPLIES FOR SLIGHTLY NEGLIGENT INFRINGEMENT OF A +MATERIAL CONTRACTUAL OBLIGATION, WHOSE FULFILLMENT IS ESSENTIAL IN ACCOMPLISHING +THE CONTRACT AND ON WHOSE FULFILLMENT THE OTHER PARTY CAN REGULARLY DEPEND +("CARDINAL DUTY"/ "KARDINALPFLICHT"). THE PARTIES SPECIFICALLY AGREE THAT THE +TYPICAL FORESEEABLE DAMAGE AND BREACHES OF A CARDINAL DUTY WILL NOT EXCEED IN +AGGREGATE THE LIABILITY CAP SET OUT IN SECTION A.4. Additional Exceptions on +Liability under Section A.4 NONE OF THE LIMITATIONS IN SECTION A.4 EXCLUDES +EITHER PARTY'S LIABILITY FOR DAMAGES DIRECTLY RESULTING FROM: (I) INTENT; (II) +GROSS NEGLIGENCE; (III) CULPABLE INJURY TO LIFE, BODY AND HEALTH; (IV) IN CASE +OF A BREACH OF GUARANTEE, WHICH MUST BE EXPLICITLY NAMED A "GUARANTEE"; OR (V) +MANDATORY LIABILITIES UNDER THE PRODUCT LIABILITY ACT. + +Netherlands and Rest of Europe. For customers located in the Netherlands and +European countries not covered by other region-specific terms above, the +following terms apply: Governing Law; Jurisdiction and Venue. This Agreement is +governed by the laws of the Netherlands and the parties submit to the exclusive +jurisdiction and venue of court located in Rotterdam. Any court proceedings will +be conducted in English, to the extent available. Additional Exceptions on +Liability under Section A.4(Limitation on Liability). NONE OF THE LIMITATIONS IN +SECTION A.4 EXCLUDES EITHER PARTY'S LIABILITY FOR EITHER PARTY'S LIABILITY FOR +INTENT OR GROSS NEGLIGENCE (OPZET OF BEWUSTE ROEKELOOSHEID) OF THAT PARTY OR ITS +MANAGERIAL STAFF. + +Australia, Zealand And Asia Pacific. For customers located in Australia and New +Zealand and Asia Pacific the following terms apply: Governing Law; Jurisdiction +and Venue. This Agreement is governed by the laws of Australia and New South +Wales and the parties submit to the exclusive jurisdiction and venue of courts +located in Sydney. + +(e) Compliance with Laws; Export. Customer will comply with U.S., foreign, and +international laws and regulations, including without limitation the U.S. +Foreign Corrupt Practices Act, U.K. Bribery Act, other anti-corruption laws, +U.S. Export Administration and Treasury Department's Office of Foreign Assets +Control regulations, and other anti-boycott and import regulations. Customer +agrees: (i) that the export, re-export, transfer, re-transfer, sale, supply, +access to, or use of the Products, Deliverables or Services to or in a country +other than the country in which the Product , Deliverables or Services were +first provided to Customer, or to, by, or for a different end user or end use +may require a U.S. or other government license or other authorization; and (ii) +not to, directly or indirectly, export, re-export, transfer, re-transfer, sell, +supply, or allow access to or use of the Products, Deliverables or Services to, +in, by, or for sanctioned, embargoed, or prohibited countries, persons, or end +uses under U.S. or other applicable law (collectively, "Prohibited Uses"). +Customer is responsible for screening for Prohibited Uses and obtaining any +required licenses or other authorizations and shall indemnify Rocket for any +violation by Customer of any applicable export controls and/or economic +sanctions laws and regulations. Rocket may terminate the Agreement and Licenses +immediately if Rocket determines, in its sole discretion, that Customer has +breached, intends to breach, or insists upon breaching any of the provisions in +this clause. + +(f) Language. The parties agree that the Agreement and all related documents are +in English. + +(g) No Agency. Each party is an independent contractor and may not commit the +other party without written authorization. The Agreement does not create an +employment, joint venture, partner, or agency relationship. + +(h) Non-Solicitation. For the Agreement term and 1 year after the termination +date, without Rocket's written consent, Customer will not, directly or +indirectly, hire or solicit any Rocket employee, former employee, or contractor +(except as a result of a generally advertised recruiting solicitation), or +attempt to or interfere with Rocket's business. + +(i) Notice. Notice or approval must be in writing signed by a party's authorized +representative, sent to the address on the Order Form or otherwise specified in +writing by a party. Notice must be sent by mail or overnight courier with return +receipt, and is effective 1 business day after being sent by overnight courier +or 3 business days after being sent by mail. + +(j) Publicity. Rocket may use Customer's name in press releases, product +brochures, and other marketing materials to indicate they are Rocket's customer. +Rocket will use Customer's trademarks, service marks, logos or branding, +according to Customer's branding guidelines, which Customer will make available +to Rocket. + +(k) Taxes. Product and Service Fees do not include taxes. Customer will pay all +sales, use, property, customs, excise, value added and other taxes ("Tax") +imposed upon the purchase, sale, license, or use of Products and/or Services, +regardless whether the Tax is included in the invoice Rocket sends to Customer, +except taxes on Rocket's net income. Fees payable by Customer will not be +reduced by any Tax and Customer will pay invoiced Fees and Tax, or Customer will +provide a tax exemption certificate or tax payment receipt prior to Rocket's +Delivery of Products or performance of Services, or proof of payment for Tax +within 30 days from invoice date. + +(l) Payment. Unless specified otherwise by Rocket in writing, Customer's payment +is due within 30 days from date of invoice. Late payment is a material breach of +Customer's obligation, upon which Rocket may suspend Product Delivery and +Service performance. Customer will pay to Rocket all reasonable costs and +expenses for collection of overdue amounts, including legal fees. Rocket may +review Customer's financial condition, payment and credit history and notify +Customer of any additional payment or credit requirements. Customer must notify +Rocket in writing of any disputed invoice within 15 days of invoice receipt or +its right to dispute the invoice will be deemed waived. Customer will pay Fees +as invoiced regardless of any warranty claim. + +9. DEFINITIONS + +(a) Affiliate means a legal entity that is controlled by Customer through +ownership of 51% or more of its outstanding equity that may order Products and +Services by executing an Order Form as a customer under these Terms, subject to +Rocket's written approval. + +(b) Concurrent User means a User authorized to use a Product or Service +concurrently with other Concurrent Users, limited by a maximum number of +Concurrent Users at any one time. + +(c) Confidential Information means any material, data, or information, in any +form or media, that is proprietary or confidential to a party and is marked as +confidential, or not marked but by its nature or treatment by its owner should +reasonably be considered to be confidential. + +(d) Customer means the legal entity executing the initial Order Form. + +(e) Day means calendar day unless specified as business day. + +(f) Deliverable means materials or work product specified as a "deliverable" in +an Order Form that Rocket provides or creates with Professional Services, +including without limitation software programming, application program +interfaces, information, documents, reports, technical and non-technical data, +specifications and other material, including derivative works. Deliverables do +not include Products. + +(g) Deliver(y) means Rocket has provided, and Customer is deemed to have +accepted, a Product through electronic access. + +(h) Disclosing Party means a party whose Confidential Information is disclosed +to the other party. + +(i) Documentation means Rocket's user manuals and training materials provided to +Customer electronically or physically. + +(j) Enterprise License means a Measured License limited to the use required +within a certain business unit or corporate entity specified in the Order Form +measured as of the Order Form date. + +(k) Fee means Rocket's price for a Product or Service specified in an Order +Form. + +(l) Intellectual Property means all intellectual property, including without +limitation, inventions, patents, copyrights, trademarks, service marks, trade +names, trade secrets, know-how, moral rights, licenses, and any other intangible +proprietary or property rights, registered or not, under statute and/or common +law. + +(m) License means Customer's non-exclusive, non-transferable right to use the +licensed Products, Services, Deliverables or materials for its own internal +business operations, according to the Documentation, and subject to the +Agreement's restrictions. + +(n) Measured License means a License for the time period, number and type of +Users, transactions, copies, seats, instructions per second (MIPS) or other +quantity or measure specified for each Product listed in an Order Form. + +(o) Named User means an individual identified User authorized to use a Product +or Service. A new Named User may replace a prior Named User. + +(p) Order Form means a quote, SOW, or registration form provided by Rocket to +Customer that includes the Products, Services, Fees and a unique Rocket +reference number for each Order Form. + +(q) Products means Rocket proprietary software products. + +(r) Product Warranty means Rocket's limited warranty for Products. + +(s) Professional Services means the professional consulting services, standard +installation, integration and configuration services, and time and materials +services Rocket provides as an independent contractor. + +(t) Receiving Party means a party receiving the other party's Confidential +Information. + +(u) Service(s) means Support Services and/or Professional Services. + +(v) Service Warranty means Rocket's limited warranty specified for Support +Services or Professional Services. + +(w) SOW means a statement of work that documents materials and services for a +project that Rocket provides, generally for Professional Services engagements, +including a project plan, resources and actions provided by each party and a +payment schedule. + +(x) Support Period means a time period defined in an Order Form during which +Rocket will provide Support Services. + +(y) Support Service(s) means Rocket's current standard maintenance and support +services, policies and procedures for Products. + +(z) User means a Named User or Concurrent User employed by and authorized by +Customer to use a Product or Service for Customer's internal business purposes. + +B. PRODUCT PURCHASE/LICENSE/MAINTENANCE SUPPORT TERMS + +1. ORDERS + +Rocket will provide an Order Form to Customer that includes the Products, +Support Services, Fees, other Services, and Rocket reference number for each +order. Customer will place a binding order, subject to Rocket's acceptance, by +sending Rocket a signed Order Form. + +2. LICENSE + +(a) Grant. Rocket grants to Customer a Measured License for each Product listed +in the Order Form, in object code form, and related Documentation. Customer may +make one copy of the Product for non-production backup purposes. Customer's +right to use the Product as an Enterprise License or a type of Measured License +is specified in the Order Form. Customer's actual use will not decrease (but may +increase) the scope of the License granted and the Fees due. + +(b) Restrictions. Customer will not: +(i) Rent, lease, or sublicense a Product, or use a Product as a service bureau +or for hosting as an application service provider; +(ii) Permit any third party to access or use a Product or Documentation, except +for Customer's Affiliates using a Product or Documentation for Customer's +internal business operations, provided Customer (a) ensures its Affiliates +comply with the terms of the Agreement and (b) is liable for their acts and +omissions; +(iii) Transfer or use a Product or Documentation to or in a country other than +that to which Rocket first provides it; +(iv) Use a Product except as specified in the Documentation; +(v) Translate, modify or make derivative works of a Product or Documentation; +(vi) Reverse engineer, , decompile or disassemble a Product, except as permitted +by law after Customer has disclosed its intended activities in writing to +Rocket; +(vii) Exceed the time period for the License, or use a Product in excess of the +Measured License or Enterprise License, which Customer purchased; +(viii) Use a Product in production if provided under a testing, evaluation, +development or other non-production License; +(ix) Alter a Product's copyright or other intellectual property rights notices; +(x) Infringe or misappropriate Rocket's or its licensors' Intellectual Property. + +(c) Verification. Customer will keep accurate records measuring its use of the +Products according to its License. Rocket has the right to audit Customer's +records and operations to verify Customer's Product use according to the License +and the Agreement. Audits will be scheduled at a mutually agreed date and time +during Customer's usual business hours. If Rocket determines that Customer's +Product use exceeds the License Customer purchased, Customer will immediately +pay Rocket the current Fees for the additional Product use, including reasonably +estimated arrears for Support Service Fees, and reimburse Rocket's reasonable +expenses to perform the audit. THE LIMITATION OF LIABILITY SET FORTH IN SECTION +A4 DOES NOT APPLY TO CUSTOMER'S PRODUCT USE EXCEEDING ITS LICENSE OR +MISAPPROPRIATION OF A PRODUCT. + +(d) Termination. Rocket may terminate a License by written notice (i) +immediately, if Customer infringes or misappropriates Rocket's or its licensors' +Intellectual Property or fails to comply with the License Terms; (ii) as +specified in the Warranty Terms; and (iii) if Customer materially breaches the +Agreement, subject to any specified cure period. Upon termination Customer will +immediately return or destroy all Product and, upon Rocket's request, provide +written certification of such destruction. + +(e) Excluded Components. The provisions of this paragraph do not apply to the +extent they are held to be invalid or unenforceable under the law that governs +this Agreement. Notwithstanding any of the terms in this Agreement or any other +agreement Licensee may have with Rocket (a) the third party suppliers of such +Excluded Components, as described in the Notices file included with the included +with the Software, (the "Suppliers") provide the components WITHOUT WARRANTIES +OF ANY KIND and, such Suppliers DISCLAIM ANY AND ALL EXPRESS AND IMPLIED +WARRANTIES AND CONDITIONS INCLUDING, BUT NOT LIMITED TO, THE WARRANTY OF TITLE, +NON-INFRINGEMENT OR INTERFERENCE AND THE IMPLIED WARRANTIES AND CONDITIONS OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE +EXCLUDED COMPONENTS; (b) the Suppliers shall not be liable for any direct, +indirect, incidental, special, exemplary, punitive or consequential damages, +including but not limited to lost data, lost savings, and lost profits, with +respect to the Excluded Components; and, (c) neither Rocket nor the Suppliers +shall be liable to Licensee for any claims arising directly or indirectly from +or related to the Excluded Components. Notices with respect to the Excluded +Components, including instructions for obtaining source code (as applicable) for +certain Excluded Components, may be found in the NOTICES file(s) that +accompanies the Software. + +3. SUPPORT SERVICES + +(a) Support Services. Rocket will provide Support Services purchased by Customer +according to Rocket's current standard policies and procedures as revised from +time to time. Rocket's standard Support Services generally include (i) +commercially reasonable efforts to resolve problems or bugs in the Product which +substantially impair the functionality described in Rocket's published technical +specifications; (ii) revisions and updates for Products containing code fixes, +improvements or enhancements to existing functionality as available; (iii) +access to online problem reporting, tracking, and self-help tools; and (iv) +telephone support for trained Customer personnel during purchased support hours. +Support Services do not include onsite support which may be purchased if +available. + +(b) Support Period; Termination. Support Service is available for a minimum 12 +month Support Period, unless a longer period is specified in an Order Form, and +the initial Support Period begins on the Product Delivery date. The Support +Period will renew automatically for subsequent Support Periods equal to the +initial Support Period unless either party provides written notice of +termination at least 60 days prior to the end of the current Support Period. +Rocket may suspend or terminate Support Service upon written notice if Customer +breaches its obligations including timely payment for any Support Period. Upon +termination Customer will, at Rocket's direction, return or destroy any Rocket +materials, Confidential Information and Documentation, and Customer will +immediately pay Rocket all fees due for the remainder of the Support Period and +any other fees accrued as of the termination date. + +4. PRODUCT DELIVERY + +All Products provided to Customer by Rocket are subject to these Terms. Risk of +loss for Products passes to Customer upon Delivery. Customer is responsible for +customs clearance, documents, and paying any customs duties and import fees. + +5. FEES AND PAYMENT + +(a) Product Fees. Customer will pay to Rocket the Product Fees according to an +Order Form, along with shipping, handling, taxes and any similar fees. + +(b) Support Service Fees. Support Service Fees for the initial Support Period +are included in the Product Order Form. Rocket will provide an Order Form or +invoice for each renewal Support Period at Rocket's current list price, and +Customer will pay the Support Service Fees when due, according to the Order Form +or invoice. Rocket may not provide renewal Support Services if Customer does not +pay the renewal Fees to Rocket prior to the end of the current Support Period. +If Customer's Support Services lapse at any time, renewal will be subject to +Rocket's re-instatement policies and fees. Payment that is invoiced in arrears +for any Support Period is due and payable on invoice date. + +6. WARRANTIES + +(a) Products. Rocket warrants that Product will perform substantially according +to Rocket's current published technical specifications on the Product Delivery +date, when used according to the Documentation. Customer must provide a written +Product Warranty claim to Rocket within 90 days of the Delivery date. Customer +must provide remote or local access to the Product if required by Rocket to +perform Product Warranty service. Rocket will repair or replace a Product not +conforming to the Product Warranty, or, at its option, refund the part of the +Product Fees paid for the Product that does not conform, and the Product License +terminates. Upon License termination, Customer will cease using and destroy the +Product. + +(b) Support Services. Rocket warrants that Support Services will be performed in +a commercially reasonable manner consistent with general industry standards that +apply to similar services. Customer must provide a written Service Warranty +claim to Rocket within 15 days after the date Rocket provided the Service. +Rocket, at its option, will re-perform Service not complying with the Service +Warranty at no additional charge, or refund the part of the Fee, if paid, for +the Service which does not comply with the Service Warranty. + +(c) Disclaimer. Product Warranty or Support Service Warranty does not cover +problems caused by (i) abuse, misuse, alteration, neglect, accident, +unauthorized repair or installation, or acts or omissions of any party other +than Rocket; (ii) electrical systems, fire or water damage, Customer's hardware, +software, networks, or systems; or (iii) Customer not using Product according to +Rocket's current published technical specifications. EXCEPT AS SET FORTH IN +SECTIONS 6(a) AND (b) ABOVE, ROCKET, ITS AFFILIATES AND LICENSORS DISCLAIM ALL +OTHER WARRANTIES, REPRESENTATIONS AND GUARANTEES, EXPRESS OR IMPLIED, ORAL OR +WRITTEN, FOR PRODUCTS OR SERVICES, THEIR USE, SUFFICIENCY, ACCURACY, +RELIABILITY, TIMELINESS, QUALITY, SUITABILITY, AVAILABILITY, OR COMPLETENESS, +STATUTORY OR OTHERWISE, INCLUDING WITHOUT LIMITATION, (i) MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, OR (ii) THAT SUPPORT +SERVICES OR OPERATION OF PRODUCTS WILL BE UNINTERRUPTED OR ERROR FREE, OR +OPERATE IN COMBINATION WITH ANY OTHER HARDWARE, SOFTWARE, SYSTEM, OR DATA; (iii) +ERRORS OR DEFECTS WILL BE CORRECTED. THIS SECTION B6 DESCRIBES ROCKET'S SOLE +LIABILITY AND CUSTOMER'S SOLE REMEDY FOR A PRODUCT OR SUPPORT SERVICE WARRANTY +CLAIM. + +C. PROFESSIONAL SERVICES + +1. PROFESSIONAL SERVICES ORDER Customer will order the Professional Services it +requires as specified in Section B(1) above, which Rocket may perform remotely +or on site as appropriate. The Order Form will describe the Professional +Services and any of the following that apply: project plan, resources and +actions provided by each party, Deliverables, Fees, expenses, and payment +schedule. + +2. PROFESSIONAL SERVICES FEES AND PAYMENT + +Customer will pay to Rocket, according to each Order Form: (a) Fees for time +and Deliverables; (b) Rocket's expenses incurred with the Professional Services; +and (c) any additional fees and expenses incurred by Rocket due to changes in +the scope of Services to be provided, Customer's failure to fulfill its +obligations in a timely manner, or reassignment of personnel or rescheduling +without Rocket's fault. Professional Services Fees are due and invoiced as +Services are performed. Customer will pay Fees and expenses for all Professional +Services and Deliverables provided until the end of each Service engagement. +Rocket will itemize invoices for expenses and provide receipts if Customer +requests. All Professional Services Rocket provides are billable, regardless of +whether the Professional Services are requested by Customer to assist with a +warranty or maintenance issue, which will be addressed by Rocket's Support +Services organization. Support for third party products is provided by the third +party supplier. + +3. DELIVERABLES + +(a) Ownership. + +(i) Rocket may designate in writing Deliverables as "Type I Deliverables," "Type +II Deliverables," or otherwise as agreed. If not specified in writing, +Deliverables are Type II Deliverables. Customer's data and Confidential +Information are Customer's exclusive property in which Customer retains all +right, title and interest, and are not Deliverables even if included with +Deliverables provided by Rocket, such as in a report or dashboard. Rocket +Products are governed by separate license terms. +(ii) Type I Deliverables are Deliverables created solely for +Customer during the Professional Service performance period in which Customer +will have all right, title, and interest, including copyright. Rocket will +retain a copy of Type I Deliverables. Rocket's Intellectual Property and +Confidential Information, in which Rocket retains all right, title and interest, +are excluded from Type I Deliverables. +(iii) Type II Deliverables are Deliverables provided or created during the +Professional Services performance period, including without limitation all +preexisting materials, in which Rocket or its affiliates have all right, title, +and interest, including copyright. Rocket will provide one copy of Type II +Deliverables to Customer. + +(b) License and Use. + +(i) Rocket grants Customer a License to use and reproduce a reasonable number of +copies, and distribute internally, Type II Deliverables' object code for its own +internal business operations only, according to the Order Form. Customer will +not reverse engineer, sell, rent, sublicense or permit a third party to use or +access Type II Deliverables. Customer's ownership of Type I Deliverables and +License for Type II Deliverables are contingent upon full payment of all fees +and expenses for Professional Services. +(ii) Customer grants Rocket (1) a nonexclusive, worldwide, royalty-free right +to use and copy Customer systems, Confidential Information and data, and use any +Customer proprietary and third party products, services and materials under +Customer's license, as necessary to provide the Professional Services, and (2) +an irrevocable, nonexclusive, royalty-free right to use, reproduce, create +derivative works, sublicense and distribute, internally and to other parties, +Type I Deliverables, excluding Customer Confidential Information and Customer +data, which is Customer's exclusive property. Customer represents and warrants +that Customer information, data and third party products, services and materials +provided to Rocket will not violate any law or third party rights. +(iii) Each party will reproduce the copyright notice or other legend on any +copies made under the license and use rights granted. + +(c) Support. Rocket does not provide Support Services for Deliverables unless +Rocket, at its option, has incorporated the Deliverables in a generally +available Product, or Rocket agrees to provide Support Services for the +Deliverable in the SOW, and Customer pays fees for the Support Services. + +(d) Termination. Rocket may terminate a License by written notice (i) +immediately, if Customer infringes Rocket's or its licensors' Intellectual +Property or fails to comply with the License Terms; or (ii) if Customer +materially breaches the Agreement, subject to any specified cure period. Upon +License termination Customer must immediately destroy licensed Deliverables and, +upon Rocket's request, and so certify in writing. + +4. PERSONNEL + +On Customer premises, Rocket personnel will comply with Customer's reasonable +rules and policies provided to Rocket in writing for such matters as working +hours, holidays and Customer security measures. Rocket will determine its +personnel to perform Professional Services in its sole discretion. The parties +will resolve any Professional Services issues in good faith. If the resolution +involves reassigning personnel, Rocket will do so as soon as practical and +commercially reasonable, according to local law. Customer agrees that +reassignment may delay Professional Services or allow Rocket to terminate +Professional Services without Rocket liability. + +5. PROFESSIONAL SERVICES WARRANTY + +(a) Warranty. Rocket warrants that Professional Services will be performed in a +commercially reasonable manner consistent with industry standards. Customer must +provide a written Professional Services Warranty claim to Rocket within 15 days +after the date Rocket performs Professional Services. Rocket, at its option, +will re-perform Professional Services that do not comply with the Professional +Services Warranty at no additional charge, or if not practical and solely at +Rocket's option, credit the part of the Professional Services Fee, if paid, for +the Professional Services that do not comply with the Professional Services +Warranty. + +(b) Disclaimer. This Professional Services Warranty does not cover problems +caused by (i) abuse, misuse, alteration, enhancements, neglect, accident, +unauthorized repair or installation, or acts or omissions of, or delay by, any +party other than Rocket; or (ii) electrical systems, fire or water damage, +Customer's hardware, software, networks, or systems. DELIVERABLES ARE PROVIDED +ON AN "AS-IS" BASIS, WITHOUT WARRANTY OF ANY KIND. ROCKET, ITS AFFILIATES AND +LICENSORS DISCLAIM ALL OTHER WARRANTIES, REPRESENTATIONS AND GUARANTEES, EXPRESS +OR IMPLIED, ORAL OR WRITTEN, FOR PROFESSIONAL SERVICES AND DELIVERABLES, THEIR +USE, SUFFICIENCY, OR ACCURACY, INCLUDING WITHOUT LIMITATION, IMPLIED WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT, OR +THAT PROFESSIONAL SERVICES OR DELIVERABLES WILL BE UNINTERRUPTED OR ERROR FREE. + +(c) Limitation. THE WARRANTY DESCRIBED IN THIS SECTION C5 IS ROCKET'S SOLE +LIABILITY AND CUSTOMER'S EXCLUSIVE REMEDY FOR A PROFESSIONAL SERVICES OR +DELIVERABLES CLAIM. + + +6. TERMINATION + +Either party may terminate a Professional Services engagement, in whole or in +part, with 30 days prior written notice, effective on the date specified in the +notice, however, these Terms apply for all Services and Deliverables provided +regardless of the termination date, including any Services provided for +transition or termination assistance. Rocket is not responsible for the +resulting condition of Services or Deliverables upon early termination. These +Terms govern all Order Forms until Professional Services are terminated or +completed. + +Rev January 2022 \ No newline at end of file diff --git a/src/licensedcode/data/licenses/salesforcesans-font.LICENSE b/src/licensedcode/data/licenses/salesforcesans-font.LICENSE new file mode 100644 index 00000000000..e9f23d679c3 --- /dev/null +++ b/src/licensedcode/data/licenses/salesforcesans-font.LICENSE @@ -0,0 +1,120 @@ +--- +key: salesforcesans-font +short_name: SalesforceSans Font License +name: SalesforceSans Font License +category: Proprietary Free +owner: Salesforce.com +homepage_url: https://github.com/salesforce-ux/design-system-ios/blob/master/SalesforceDesignSystem.bundle/License-for-SalesforceSans-font.txt +spdx_license_key: LicenseRef-scancode-salesforcesans-font +ignorable_copyrights: + - Copyright 2015 Salesforce.com +ignorable_holders: + - Salesforce.com +--- + +FONT LICENSE AGREEMENT + +THIS FONT LICENSE AGREEMENT (“AGREEMENT”) IS A LEGAL AGREEMENT BETWEEN YOU AND +SALESFORCE.COM, INC. (“WE”, “US”, “OUR”, AND “SALESFORCE”) THAT GOVERNS YOUR +ACQUISITION AND USE OF THE SALESFORCE SANS FONT (E.G., TYPEFACE, TYPOGRAPHIC +CHARACTERS, ALPHANUMERICS, SYMBOLS, DESIGNS, AND ORNAMENTS) AND THE RELATED +FONT FILES (E.G., TRUETYPE (TTF), WEB OPEN FONT FORMAT (WOFF,WOFF2), EMBEDDED +OPENTYPE (EOT), AND SCALABLE VECTOR GRAPHICS (SVG) FILES) (COLLECTIVELY, THE +“FONT”). BY DOWNLOADING OR USING THE FONT, YOU AGREE TO THE TERMS OF THIS +AGREEMENT. IF YOU ARE DOWNLOADING OR USING THE FONT ON BEHALF OF A COMPANY OR +OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH +ENTITY AND ITS AFFILIATES TO THIS AGREEMENT, IN WHICH CASE THE TERMS “YOU” OR +“YOUR” WILL REFER TO SUCH ENTITY AND ITS AFFILIATES. IF YOU DO NOT HAVE SUCH +AUTHORITY, OR IF YOU DO NOT AGREE WITH THE TERMS OF THIS AGREEMENT, YOU MUST +NOT DOWNLOAD OR USE THE FONT. This Agreement was last updated on August 21, +2015. It is effective between You and Us as of the date You accept this +Agreement by downloading or using the Font. + +1. License Grant +Subject to the terms of this Agreement and any other +applicable Salesforce terms, conditions, and acceptable use policies (AUPs), +We hereby grant to You a revocable, non-transferable, non-exclusive, and non- +sublicenseable limited license to, without modification, reproduce and use the +Font solely to create applications with the Salesforce Lightning Design System +that run in Salesforce or on a Salesforce platform (e.g., Lightning, Heroku, +Visualforce) (“Applications”). + +2. Restrictions +To the extent your Application contains copyright notices, +together with all other copyright notices included with each Application, You +will include the following copyright notice: “The Salesforce Sans Font is used +under license from salesforce.com, inc. Copyright 2015 Salesforce.com, Inc.” +You may not modify, adapt, translate, reverse engineer, decompile, +disassemble, or create derivative works based on the Font. You must include +the Font in an Application in a manner that does not allow a user to access +the Font outside of the Application. You will not use the Font on a +standalone basis and will only use the Font as part of the Salesforce +Lightning Design System. You must not take any action which will have the +direct or indirect effect of causing the Font to become subject to the terms +of an open source license or any similar terms. You may refer to the Font as +“Salesforce Sans”, but You may not use any other Salesforce trademark in +connection with the Font except as may be expressly agreed to by Salesforce in +writing or as set forth in other applicable Salesforce terms, conditions, and +acceptable use policies (AUPs) and in any event You must comply at all times +with the Salesforce Trademark and Copyright Usage Guidelines located at http:/ +/www2.sfdcstatic.com/assets/pdf/misc/salesforce_Trademark_Usage_Guidelines.pdf +and any other supplemental guidelines that may apply to you. You must not +license, sublicense, sell, resell, rent, lease, transfer, assign, distribute, +time share, or otherwise commercially exploit the Font nor make the Font +available to any third party, other than as expressly permitted by this +Agreement. To the extent any Font documentation, style guides, or other +applicable Salesforce terms, conditions, and acceptable use policies (AUPs) +impose guidelines or restrictions for the use of the Font, You will abide by +those guidelines and restrictions. + +3. Ownership +Subject to the limited rights expressly granted hereunder, We +reserve all rights, title, and interest in and to the Font, including all +related intellectual property rights. No rights are granted to You hereunder +other than as expressly set forth herein. We shall have a royalty-free, +worldwide, irrevocable, perpetual license to use and incorporate into the Font +any suggestions, enhancement requests, recommendations, or other feedback +provided by You. + +4. Term and Termination +This Agreement will take effect when you download or +use the Font and will terminate upon the earlier of: (a) Your failure to +comply with any term of this Agreement or any other applicable Salesforce +terms, conditions, and acceptable use policies (AUPs); (b) return, +destruction, or deletion of all copies of the Font in your possession; or, (c) +60 days after Salesforce provides You with written notice of termination. +Salesforce’s rights and your obligations will survive the termination of this +Agreement. Upon termination of this Agreement by Salesforce, if requested by +Salesforce, you will destroy or delete all copies of the Font in your +possession and cease using the Font in all Applications. + +5. No Warranty +THE FONT IS PROVIDED “AS-IS,” EXCLUSIVE OF ANY WARRANTY +WHATSOEVER. WE DISCLAIM ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION +ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +TITLE, AND NON-INFRINGEMENT. The Font may contain bugs or errors. Any use of +the Font is at Your sole risk. You acknowledge that We may discontinue making +the Font available to You at any time in Our sole discretion. + +6. No Damages +IN NO EVENT SHALL WE HAVE ANY LIABILITY HEREUNDER TO YOU FOR +ANY DAMAGES WHATSOEVER, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES, OR DAMAGES BASED ON +LOST PROFITS, DATA OR USE, HOWEVER CAUSED AND, WHETHER IN CONTRACT, TORT OR +UNDER ANY OTHER THEORY OF LIABILITY, WHETHER OR NOT YOU HAVE BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES. + +7. General Provisions +You may not assign any of Your rights or obligations +hereunder, whether by operation of law or otherwise, without Our prior written +consent. This Agreement shall be governed exclusively by the internal laws of +the State of California, without regard to its conflicts of laws rules. Each +party hereby consents to the exclusive jurisdiction of the state and federal +courts located in San Francisco County, California to adjudicate any dispute +arising out of or relating to this Agreement. This Agreement constitutes the +entire agreement between the parties, and supersedes all prior and +contemporaneous agreements, proposals or representations, written or oral, +concerning its subject matter. No modification, amendment, or waiver of any +provision of this Agreement shall be effective unless in writing and either +signed or accepted electronically by the party against whom the modification, +amendment or waiver is to be asserted. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/snowplow-cla-1.0.LICENSE b/src/licensedcode/data/licenses/snowplow-cla-1.0.LICENSE new file mode 100644 index 00000000000..154f9115a0a --- /dev/null +++ b/src/licensedcode/data/licenses/snowplow-cla-1.0.LICENSE @@ -0,0 +1,62 @@ +--- +key: snowplow-cla-1.0 +short_name: Snowplow Community License Agreement 1.0 +name: Snowplow Community License Agreement 1.0 +category: Proprietary Free +owner: Snowplow +homepage_url: https://docs.snowplow.io/community-license-1.0/ +spdx_license_key: LicenseRef-scancode-snowplow-cla-1.0 +text_urls: + - https://github.com/snowplow/snowbridge/blob/7cda9fb263232b0e0736dedab2b85132ac682865/LICENCE.md +ignorable_urls: + - https://docs.snowplow.io/community-license-1.0 +--- + +Snowplow Community License Agreement + +Version 1.0, January 2023 + +This Snowplow Community License Agreement, Version 1.0 (the “Agreement”) sets forth the terms on which Snowplow Analytics, Ltd. (“Snowplow”) makes available certain software made available by Snowplow under this Agreement (the “Software”). BY INSTALLING, DOWNLOADING, ACCESSING, OR USING ANY OF THE SOFTWARE, YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO SUCH TERMS AND CONDITIONS, YOU MUST NOT USE THE SOFTWARE. IF YOU ARE RECEIVING THE SOFTWARE ON BEHALF OF A LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU HAVE THE ACTUAL AUTHORITY TO AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT ON BEHALF OF SUCH ENTITY. “Licensee” means you, an individual, or the entity on whose behalf you are receiving the Software. +LICENSE GRANT AND CONDITIONS + +1.1 License. Subject to the terms and conditions of this Agreement, Snowplow hereby grants to Licensee a non-exclusive, royalty-free, worldwide, non-transferable, non-sublicenseable license during the term of this Agreement to: (a) use the Software; (b) prepare modifications and derivative works of the Software; and (c) reproduce copies of the Software (the “License”). No right to distribute or make available the Software is granted under this License. Licensee is not granted the right to, and Licensee shall not, exercise the License for an Excluded Purpose. For purposes of this Agreement, “Excluded Purpose” means making available any on-premises or distributed software product, software-as-a-service, platform-as-a-service, infrastructure-as-a-service, or other similar online service, that competes with any products or services that Snowplow or any of its affiliates provides using the Software. + +1.2 Conditions. In consideration of the License, Licensee’s distribution of the Software is subject to the following conditions: + + a. Licensee must cause any Software modified by Licensee to carry prominent notices stating that Licensee modified the Software. + + b. On each Software copy, Licensee shall reproduce and not remove or alter all Snowplow or third party copyright or other proprietary notices contained in the Software, and Licensee must include the notice below on each copy. + + This software is made available by Snowplow Analytics, Ltd., + under the terms of the Snowplow Community License Agreement, Version 1.0 + located at https://docs.snowplow.io/community-license-1.0 + BY INSTALLING, DOWNLOADING, ACCESSING, USING OR DISTRIBUTING ANY OF THE SOFTWARE, + YOU AGREE TO THE TERMS OF SUCH LICENSE AGREEMENT. + +1.3 Licensee Modifications. Licensee may add its own copyright notices to modifications made by Licensee. + +1.4 No Sublicensing. The License does not include the right to sublicense the Software, however, each recipient to which Licensee provides the Software may exercise the Licenses so long as such recipient agrees to the terms and conditions of this Agreement. + +TERM AND TERMINATION + +This Agreement will continue unless and until earlier terminated as set forth herein. If Licensee breaches any of its conditions or obligations under this Agreement, this Agreement will terminate automatically and the License will terminate automatically and permanently. + +INTELLECTUAL PROPERTY + +As between the parties, Snowplow will retain all right, title, and interest in the Software, and all intellectual property rights therein. Snowplow hereby reserves all rights not expressly granted to Licensee in this Agreement. Snowplow hereby reserves all rights in its trademarks and service marks, and no licenses therein are granted in this Agreement. + +DISCLAIMER + +SNOWPLOW HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE SOFTWARE. + +LIMITATION OF LIABILITY + +SNOWPLOW WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO, LOST PROFITS OR ANY CONSEQUENTIAL, SPECIAL, INCIDENTAL, INDIRECT, OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ARISING OUT OF THIS AGREEMENT. THE FOREGOING SHALL APPLY TO THE EXTENT PERMITTED BY APPLICABLE LAW. + +GENERAL + +6.1 Governing Law. This Agreement will be governed by and interpreted in accordance with the laws of the state of Delaware, without reference to its conflict of laws principles. If Licensee is located within the United States, all disputes arising out of this Agreement are subject to the exclusive jurisdiction of courts located in Delaware, USA. If Licensee is located outside of the United States, any dispute, controversy or claim arising out of or relating to this Agreement will be referred to and finally determined by arbitration in accordance with the JAMS International Arbitration Rules. The tribunal will consist of one arbitrator. The place of arbitration will be in the State of Delaware, USA. The language to be used in the arbitral proceedings will be English. Judgment upon the award rendered by the arbitrator may be entered in any court having jurisdiction thereof. + +6.2. Assignment. Licensee is not authorized to assign its rights under this Agreement to any third party. Snowplow may freely assign its rights under this Agreement to any third party. + +6.3. Other. This Agreement is the entire agreement between the parties regarding the subject matter hereof. No amendment or modification of this Agreement will be valid or binding upon the parties unless made in writing and signed by the duly authorized representatives of both parties. In the event that any provision, including without limitation any condition, of this Agreement is held to be unenforceable, this Agreement and all licenses and rights granted hereunder will immediately terminate. Waiver by Snowplow of a breach of any provision of this Agreement or the failure by Snowplow to exercise any right hereunder will not be construed as a waiver of any subsequent breach of that right or as a waiver of any other right. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/snowplow-lula-1.0.LICENSE b/src/licensedcode/data/licenses/snowplow-lula-1.0.LICENSE new file mode 100644 index 00000000000..92ee7b3d8da --- /dev/null +++ b/src/licensedcode/data/licenses/snowplow-lula-1.0.LICENSE @@ -0,0 +1,68 @@ +--- +key: snowplow-lula-1.0 +short_name: Snowplow Limited Use License 1.0 +name: Snowplow Limited Use License Agreement 1.0 +category: Proprietary Free +owner: Snowplow +homepage_url: https://docs.snowplow.io/limited-use-license-1.0/ +spdx_license_key: LicenseRef-scancode-snowplow-lula-1.0 +text_urls: + - https://github.com/snowplow/snowbridge/blob/b72cd4a85e027bba39c8e924a5e9a94c6ff79836/LICENSE.md +ignorable_urls: + - https://docs.snowplow.io/limited-use-license-1.0 +--- + +Snowplow Limited Use License Agreement + +Version 1.0, January 2024 + +This Snowplow Limited Use License Agreement, Version 1.0 (the “Agreement”) sets forth the terms on which Snowplow Analytics, Ltd. (“Snowplow”) makes available certain software (the “Software”). BY INSTALLING, DOWNLOADING, ACCESSING, OR USING ANY OF THE SOFTWARE, YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO SUCH TERMS AND CONDITIONS, YOU MUST NOT USE THE SOFTWARE. IF YOU ARE RECEIVING THE SOFTWARE ON BEHALF OF A LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU HAVE THE ACTUAL AUTHORITY TO AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT ON BEHALF OF SUCH ENTITY. “Licensee” means you, an individual, or the entity on whose behalf you are receiving the Software. +LICENSE GRANT AND CONDITIONS + +1.1 License. Subject to the terms and conditions of this Agreement, Snowplow hereby grants to Licensee a non-exclusive, royalty-free, worldwide, non-transferable, non-sublicensable license during the term of this Agreement to: (a) use the Software; (b) prepare modifications and derivative works of the Software; and (c) reproduce copies of the Software (the “License”). No right to distribute or make available the Software is granted under this License. Licensee is not granted the right to, and Licensee shall not, exercise the License for any Excluded Purpose. + +1.2 For purposes of this Agreement, an “Excluded Purpose” is any use that is either a Competing Use or a Highly-Available Production Use, or both of them. + + 1.2.1 A “Competing Use” is making available any on-premises or distributed software product, or any software-as-a-service, platform-as-a-service, infrastructure-as-a-service, or other similar online service, that competes with any products or services that Snowplow or any of its affiliates provides using the Software. + + 1.2.2 Highly-Available Production Use is any highly-available use, including without limitation any use where multiple instances of any Software component run concurrently to avoid a single point of failure, in a production environment, where production means use on live data. + +1.3 Conditions. In consideration of the License, Licensee’s use of the Software is subject to the following conditions: + + a. Licensee must cause any Software modified by Licensee to carry prominent notices stating that Licensee modified the Software. + + b. On each Software copy, Licensee shall reproduce and not remove or alter all Snowplow or third party copyright or other proprietary notices contained in the Software, and Licensee must include the notice below on each copy. + + This software is made available by Snowplow Analytics, Ltd., + under the terms of the Snowplow Limited Use License Agreement, Version 1.0 + located at https://docs.snowplow.io/limited-use-license-1.0 + BY INSTALLING, DOWNLOADING, ACCESSING, USING OR DISTRIBUTING ANY PORTION + OF THE SOFTWARE, YOU AGREE TO THE TERMS OF SUCH LICENSE AGREEMENT. + +1.4 Licensee Modifications. Licensee may add its own copyright notices to modifications made by Licensee. + +1.5 No Sublicensing. The License does not include the right to sublicense the Software, however, each recipient to which Licensee provides the Software may exercise the Licenses so long as such recipient agrees to the terms and conditions of this Agreement. + +TERM AND TERMINATION + +This Agreement will continue unless and until earlier terminated as set forth herein. If Licensee breaches any of its conditions or obligations under this Agreement, this Agreement will terminate automatically and the License will terminate automatically and permanently. + +INTELLECTUAL PROPERTY + +As between the parties, Snowplow will retain all right, title, and interest in the Software, and all intellectual property rights therein. Snowplow hereby reserves all rights not expressly granted to Licensee in this Agreement. Snowplow hereby reserves all rights in its trademarks and service marks, and no licenses therein are granted in this Agreement. + +DISCLAIMER + +SNOWPLOW HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE SOFTWARE. + +LIMITATION OF LIABILITY + +SNOWPLOW WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO LOST PROFITS OR ANY CONSEQUENTIAL, SPECIAL, INCIDENTAL, INDIRECT, OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ARISING OUT OF THIS AGREEMENT. THE FOREGOING SHALL APPLY TO THE EXTENT PERMITTED BY APPLICABLE LAW. + +GENERAL + +6.1 Governing Law. This Agreement will be governed by and interpreted in accordance with the laws of the state of Delaware, without reference to its conflict of laws principles. If Licensee is located within the United States, all disputes arising out of this Agreement are subject to the exclusive jurisdiction of courts located in Delaware, USA. If Licensee is located outside of the United States, any dispute, controversy or claim arising out of or relating to this Agreement will be referred to and finally determined by arbitration in accordance with the JAMS International Arbitration Rules. The tribunal will consist of one arbitrator. The place of arbitration will be in the State of Delaware, USA. The language to be used in the arbitral proceedings will be English. Judgment upon the award rendered by the arbitrator may be entered in any court having jurisdiction thereof. + +6.2. Assignment. Licensee is not authorized to assign its rights under this Agreement to any third party. Snowplow may freely assign its rights under this Agreement to any third party. + +6.3. Other. This Agreement is the entire agreement between the parties regarding the subject matter hereof. No amendment or modification of this Agreement will be valid or binding upon the parties unless made in writing and signed by the duly authorized representatives of both parties. In the event that any provision, including without limitation any condition, of this Agreement is held to be unenforceable, this Agreement and all licenses and rights granted hereunder will immediately terminate. Waiver by Snowplow of a breach of any provision of this Agreement or the failure by Snowplow to exercise any right hereunder will not be construed as a waiver of any subsequent breach of that right or as a waiver of any other right. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/snowplow-person-academic-1.0.LICENSE b/src/licensedcode/data/licenses/snowplow-person-academic-1.0.LICENSE new file mode 100644 index 00000000000..13c41398f91 --- /dev/null +++ b/src/licensedcode/data/licenses/snowplow-person-academic-1.0.LICENSE @@ -0,0 +1,67 @@ +--- +key: snowplow-person-academic-1.0 +short_name: Snowplow Personal-Academic License 1.0 +name: Snowplow Personal & Academic License Agreement 1.0 +category: Proprietary Free +owner: Snowplow +homepage_url: https://github.com/snowplow/dbt-snowplow-normalize/blob/main/LICENSE +spdx_license_key: LicenseRef-scancode-snowplow-person-academic-1.0 +--- + +# Snowplow Personal & Academic License Agreement + +_Version 1.0, September 2023_ + +## Acceptance + +In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses. + +## Copyright License + +The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it, but only for any non-commercial purpose. + +Non-commercial purposes include only: + +* Personal use for research, experiment, personal study, or hobby projects, without any anticipated commercial application. +* Use for teaching purposes by lecturers of a school or university. +* Use to evaluate the sufficiency of the software for the commercial needs of you or your company. + +## Notices + +You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above. + +## Patent License + +The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software for a non-commercial purpose. + +## Fair Use + +You may have "fair use" rights for the software under the law. These terms do not limit them. + +## No Other Rights + +These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses. + +## Patent Defense + +If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company. + +## Violations + +The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately. + +## No Liability + +**As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.** + +## Definitions + +The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms. + +**You** refers to the individual or entity agreeing to these terms. + +**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect. + +**Your licenses** are all the licenses granted to you for the software under these terms. + +**Use** means anything you do with the software requiring one of your licenses. \ No newline at end of file From 8c7d74128722abb0cb03c251eb94ae0dacf86078 Mon Sep 17 00:00:00 2001 From: alexzurbonsen Date: Mon, 16 Dec 2024 16:05:52 +0100 Subject: [PATCH 06/29] Fix missing spdx license expression in license detection Occassionally, the spdx license expression is missing in license detections even though the license expression itself is non-null and a matching spdx expression would be available. At least some instances of this bug are due to post processing of detections, in which only the license expression but not the spdx license expression is corrected for license clues that are converted to license detections in post processing. Signed-off-by: alexzurbonsen --- src/licensedcode/detection.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/licensedcode/detection.py b/src/licensedcode/detection.py index 7e5bf1dcf8a..03f91150846 100644 --- a/src/licensedcode/detection.py +++ b/src/licensedcode/detection.py @@ -1907,6 +1907,7 @@ def process_detections(detections, licensing=Licensing()): for key in license_keys ): detection.license_expression = license_expression + detection.license_expression_spdx = detection.spdx_license_expression() detection.detection_log.append(DetectionRule.NOT_LICENSE_CLUES.value) detection.identifier = detection.identifier_with_expression From 34e3996e032b8b498daafa3c0a92e9d82005cfeb Mon Sep 17 00:00:00 2001 From: Aayush Kumar Date: Wed, 18 Dec 2024 22:18:12 +0530 Subject: [PATCH 07/29] Enforced --path as a required parameter for scancode-license-data module Signed-off-by: Aayush Kumar --- src/licensedcode/license_db.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/licensedcode/license_db.py b/src/licensedcode/license_db.py index f460e88f061..091d3aadf20 100644 --- a/src/licensedcode/license_db.py +++ b/src/licensedcode/license_db.py @@ -210,6 +210,7 @@ def scancode_license_data(path): '--path', type=click.Path(exists=False, writable=True, file_okay=False, resolve_path=True, path_type=str), metavar='DIR', + required=True, help='Dump the license data in this directory in the LicenseDB format and exit. ' 'Creates the directory if it does not exist. ', help_group=MISC_GROUP, From 5e762a69a5618801a68d58c59898f0f15207f9f1 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Fri, 20 Dec 2024 16:59:32 +0530 Subject: [PATCH 08/29] Add rust binary parsing support Get packages, dependencies and binary symbols from parsing Rust binaries, using rust-inspector. Signed-off-by: Ayan Sinha Mahapatra --- CHANGELOG.rst | 5 +- .../reference/available_package_parsers.rst | 141 ++++++++++++++++++ setup-mini.cfg | 2 +- setup.cfg | 2 +- src/packagedcode/__init__.py | 6 + src/packagedcode/models.py | 6 +- src/packagedcode/plugin_package.py | 4 + .../templates/available_package_parsers.rst | 2 + 8 files changed, 162 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c9507e4e512..c80923a1a6e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,7 +14,7 @@ v33.0.0 (next next, roadmap) - Dependencies for - Support for copyright detection objects. -- We can now collect packages from a Go binary using go-inspector (Linux-only) +- We can now collect packages from a Rust binary using rust-inspector (Linux-only) - A new field in packages with the license category for the detected license expression and also an API function to @@ -89,6 +89,9 @@ Changes in Output Data Structure: - Drop python 3.8 support as this is end of life. Please use older releases if you are using python 3.8 but this is not recommended. +- We can now collect packages from a Go binary using go-inspector (Linux-only) + See https://github.com/aboutcode-org/scancode-toolkit/pull/3894 + v32.2.1 - 2024-07-02 --------------------- diff --git a/docs/source/reference/available_package_parsers.rst b/docs/source/reference/available_package_parsers.rst index eb593d62856..d97f897020d 100644 --- a/docs/source/reference/available_package_parsers.rst +++ b/docs/source/reference/available_package_parsers.rst @@ -20,42 +20,49 @@ parsers in scancode-toolkit during documentation builds. * - Description - Path Patterns - Package type + - Supported OS for detection - Datasource ID - Primary Language - Documentation URL * - AboutCode ABOUT file - ``*.ABOUT`` - ``about`` + - ``linux``, ``win``, ``mac`` - ``about_file`` - None - https://aboutcode-toolkit.readthedocs.io/en/latest/specification.html * - Alpine Linux .apk package archive - ``*.apk`` - ``alpine`` + - ``linux``, ``win``, ``mac`` - ``alpine_apk_archive`` - None - https://wiki.alpinelinux.org/wiki/Alpine_package_format * - Alpine Linux APKBUILD package script - ``*APKBUILD`` - ``alpine`` + - ``linux``, ``win``, ``mac`` - ``alpine_apkbuild`` - None - https://wiki.alpinelinux.org/wiki/APKBUILD_Reference * - Alpine Linux installed package database - ``*lib/apk/db/installed`` - ``alpine`` + - ``linux``, ``win``, ``mac`` - ``alpine_installed_db`` - None - None * - Android application package - ``*.apk`` - ``android`` + - ``linux``, ``win``, ``mac`` - ``android_apk`` - Java - https://en.wikipedia.org/wiki/Apk_(file_format) * - Android library archive - ``*.aar`` - ``android_lib`` + - ``linux``, ``win``, ``mac`` - ``android_aar_library`` - Java - https://developer.android.com/studio/projects/android-library @@ -63,24 +70,28 @@ parsers in scancode-toolkit during documentation builds. - ``*/configure`` ``*/configure.ac`` - ``autotools`` + - ``linux``, ``win``, ``mac`` - ``autotools_configure`` - None - https://www.gnu.org/software/automake/ * - Apache Axis2 module archive - ``*.mar`` - ``axis2`` + - ``linux``, ``win``, ``mac`` - ``axis2_mar`` - Java - https://axis.apache.org/axis2/java/core/docs/modules.html * - Apache Axis2 module.xml - ``*/meta-inf/module.xml`` - ``axis2`` + - ``linux``, ``win``, ``mac`` - ``axis2_module_xml`` - Java - https://axis.apache.org/axis2/java/core/docs/modules.html * - Bazel BUILD - ``*/BUILD`` - ``bazel`` + - ``linux``, ``win``, ``mac`` - ``bazel_build`` - None - https://bazel.build/ @@ -88,24 +99,28 @@ parsers in scancode-toolkit during documentation builds. - ``*/bower.json`` ``*/.bower.json`` - ``bower`` + - ``linux``, ``win``, ``mac`` - ``bower_json`` - JavaScript - https://bower.io * - Buck file - ``*/BUCK`` - ``buck`` + - ``linux``, ``win``, ``mac`` - ``buck_file`` - None - https://buck.build/ * - Buck metadata file - ``*/METADATA.bzl`` - ``buck`` + - ``linux``, ``win``, ``mac`` - ``buck_metadata`` - None - https://buck.build/ * - Microsoft cabinet archive - ``*.cab`` - ``cab`` + - ``linux``, ``win``, ``mac`` - ``microsoft_cabinet`` - C - https://docs.microsoft.com/en-us/windows/win32/msi/cabinet-files @@ -113,6 +128,7 @@ parsers in scancode-toolkit during documentation builds. - ``*/Cargo.lock`` ``*/cargo.lock`` - ``cargo`` + - ``linux``, ``win``, ``mac`` - ``cargo_lock`` - Rust - https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html @@ -120,114 +136,133 @@ parsers in scancode-toolkit during documentation builds. - ``*/Cargo.toml`` ``*/cargo.toml`` - ``cargo`` + - ``linux``, ``win``, ``mac`` - ``cargo_toml`` - Rust - https://doc.rust-lang.org/cargo/reference/manifest.html * - Chef cookbook metadata.json - ``*/metadata.json`` - ``chef`` + - ``linux``, ``win``, ``mac`` - ``chef_cookbook_metadata_json`` - Ruby - https://docs.chef.io/config_rb_metadata/ * - Chef cookbook metadata.rb - ``*/metadata.rb`` - ``chef`` + - ``linux``, ``win``, ``mac`` - ``chef_cookbook_metadata_rb`` - Ruby - https://docs.chef.io/config_rb_metadata/ * - Chrome extension - ``*.crx`` - ``chrome`` + - ``linux``, ``win``, ``mac`` - ``chrome_crx`` - JavaScript - https://chrome.google.com/extensions * - Cocoapods Podfile - ``*Podfile`` - ``cocoapods`` + - ``linux``, ``win``, ``mac`` - ``cocoapods_podfile`` - Objective-C - https://guides.cocoapods.org/using/the-podfile.html * - Cocoapods Podfile.lock - ``*Podfile.lock`` - ``cocoapods`` + - ``linux``, ``win``, ``mac`` - ``cocoapods_podfile_lock`` - Objective-C - https://guides.cocoapods.org/using/the-podfile.html * - Cocoapods .podspec - ``*.podspec`` - ``cocoapods`` + - ``linux``, ``win``, ``mac`` - ``cocoapods_podspec`` - Objective-C - https://guides.cocoapods.org/syntax/podspec.html * - Cocoapods .podspec.json - ``*.podspec.json`` - ``cocoapods`` + - ``linux``, ``win``, ``mac`` - ``cocoapods_podspec_json`` - Objective-C - https://guides.cocoapods.org/syntax/podspec.html * - PHP composer manifest - ``*composer.json`` - ``composer`` + - ``linux``, ``win``, ``mac`` - ``php_composer_json`` - PHP - https://getcomposer.org/doc/04-schema.md * - PHP composer lockfile - ``*composer.lock`` - ``composer`` + - ``linux``, ``win``, ``mac`` - ``php_composer_lock`` - PHP - https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control * - conan external source - ``*/conandata.yml`` - ``conan`` + - ``linux``, ``win``, ``mac`` - ``conan_conandata_yml`` - C++ - https://docs.conan.io/2/tutorial/creating_packages/handle_sources_in_packages.html#using-the-conandata-yml-file * - conan recipe - ``*/conanfile.py`` - ``conan`` + - ``linux``, ``win``, ``mac`` - ``conan_conanfile_py`` - C++ - https://docs.conan.io/2.0/reference/conanfile.html * - Conda meta.yml manifest - ``*/meta.yaml`` - ``conda`` + - ``linux``, ``win``, ``mac`` - ``conda_meta_yaml`` - None - https://docs.conda.io/ * - CPAN Perl dist.ini - ``*/dist.ini`` - ``cpan`` + - ``linux``, ``win``, ``mac`` - ``cpan_dist_ini`` - Perl - https://metacpan.org/pod/Dist::Zilla::Tutorial * - CPAN Perl Makefile.PL - ``*/Makefile.PL`` - ``cpan`` + - ``linux``, ``win``, ``mac`` - ``cpan_makefile`` - Perl - https://www.perlmonks.org/?node_id=128077 * - CPAN Perl module MANIFEST - ``*/MANIFEST`` - ``cpan`` + - ``linux``, ``win``, ``mac`` - ``cpan_manifest`` - Perl - https://metacpan.org/pod/Module::Manifest * - CPAN Perl META.json - ``*/META.json`` - ``cpan`` + - ``linux``, ``win``, ``mac`` - ``cpan_meta_json`` - Perl - https://metacpan.org/pod/Parse::CPAN::Meta * - CPAN Perl META.yml - ``*/META.yml`` - ``cpan`` + - ``linux``, ``win``, ``mac`` - ``cpan_meta_yml`` - Perl - https://metacpan.org/pod/CPAN::Meta::YAML * - CRAN package DESCRIPTION - ``*/DESCRIPTION`` - ``cran`` + - ``linux``, ``win``, ``mac`` - ``cran_description`` - R - https://r-pkgs.org/description.html @@ -235,24 +270,28 @@ parsers in scancode-toolkit during documentation builds. - ``*/control.tar.gz-extract/control`` ``*/control.tar.xz-extract/control`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_control_extracted_deb`` - None - https://www.debian.org/doc/debian-policy/ch-controlfields.html * - Debian control file - source layout - ``*/debian/control`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_control_in_source`` - None - https://www.debian.org/doc/debian-policy/ch-controlfields.html * - Debian machine readable file in source - ``*usr/share/doc/*/copyright`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_copyright_in_package`` - None - https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ * - Debian machine readable file in source - ``*/debian/copyright`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_copyright_in_source`` - None - https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ @@ -260,36 +299,42 @@ parsers in scancode-toolkit during documentation builds. - ``*/copyright`` ``*_copyright`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_copyright_standalone`` - None - https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ * - Debian binary package archive - ``*.deb`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_deb`` - None - https://manpages.debian.org/unstable/dpkg-dev/deb.5.en.html * - Debian distroless installed database - ``*var/lib/dpkg/status.d/*`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_distroless_installed_db`` - None - https://www.debian.org/doc/debian-policy/ch-controlfields.html * - Debian installed file paths list - ``*var/lib/dpkg/info/*.list`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_installed_files_list`` - None - None * - Debian installed file MD5 and paths list - ``*var/lib/dpkg/info/*.md5sums`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_installed_md5sums`` - None - https://www.debian.org/doc/manuals/debian-handbook/sect.package-meta-information.en.html#sect.configuration-scripts * - Debian installed packages database - ``*var/lib/dpkg/status`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_installed_status_db`` - None - https://www.debian.org/doc/debian-policy/ch-controlfields.html @@ -297,6 +342,7 @@ parsers in scancode-toolkit during documentation builds. - ``*/control.tar.gz-extract/md5sums`` ``*/control.tar.xz-extract/md5sums`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_md5sums_in_extracted_deb`` - None - https://www.debian.org/doc/manuals/debian-handbook/sect.package-meta-information.en.html#sect.configuration-scripts @@ -304,12 +350,14 @@ parsers in scancode-toolkit during documentation builds. - ``*.orig.tar.xz`` ``*.orig.tar.gz`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_original_source_tarball`` - None - https://manpages.debian.org/unstable/dpkg-dev/deb.5.en.html * - Debian source control file - ``*.dsc`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_source_control_dsc`` - None - https://wiki.debian.org/dsc @@ -317,6 +365,7 @@ parsers in scancode-toolkit during documentation builds. - ``*.debian.tar.xz`` ``*.debian.tar.gz`` - ``deb`` + - ``linux``, ``win``, ``mac`` - ``debian_source_metadata_tarball`` - None - https://manpages.debian.org/unstable/dpkg-dev/deb.5.en.html @@ -324,42 +373,49 @@ parsers in scancode-toolkit during documentation builds. - ``*.dmg`` ``*.sparseimage`` - ``dmg`` + - ``linux``, ``win``, ``mac`` - ``apple_dmg`` - None - https://en.wikipedia.org/wiki/Apple_Disk_Image * - Java EAR application.xml - ``*/META-INF/application.xml`` - ``ear`` + - ``linux``, ``win``, ``mac`` - ``java_ear_application_xml`` - Java - https://en.wikipedia.org/wiki/EAR_(file_format) * - Java EAR Enterprise application archive - ``*.ear`` - ``ear`` + - ``linux``, ``win``, ``mac`` - ``java_ear_archive`` - Java - https://en.wikipedia.org/wiki/EAR_(file_format) * - FreeBSD compact package manifest - ``*/+COMPACT_MANIFEST`` - ``freebsd`` + - ``linux``, ``win``, ``mac`` - ``freebsd_compact_manifest`` - None - https://www.freebsd.org/cgi/man.cgi?pkg-create(8)#MANIFEST_FILE_DETAILS * - RubyGems gem package archive - ``*.gem`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gem_archive`` - Ruby - https://web.archive.org/web/20220326093616/https://piotrmurach.com/articles/looking-inside-a-ruby-gem/ * - RubyGems gem package extracted archive - ``*/metadata.gz-extract`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gem_archive_extracted`` - Ruby - https://web.archive.org/web/20220326093616/https://piotrmurach.com/articles/looking-inside-a-ruby-gem/ * - RubyGems gemspec manifest - installed vendor/bundle/specifications layout - ``*/specifications/*.gemspec`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gem_gemspec_installed_specifications`` - Ruby - https://guides.rubygems.org/specification-reference/ @@ -368,72 +424,91 @@ parsers in scancode-toolkit during documentation builds. ``*/*.gemfile`` ``*/Gemfile-*`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemfile`` - Ruby - https://bundler.io/man/gemfile.5.html * - RubyGems Bundler Gemfile - extracted layout - ``*/data.gz-extract/Gemfile`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemfile_extracted`` - Ruby - https://bundler.io/man/gemfile.5.html * - RubyGems Bundler Gemfile.lock - ``*/Gemfile.lock`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemfile_lock`` - Ruby - https://bundler.io/man/gemfile.5.html * - RubyGems Bundler Gemfile.lock - extracted layout - ``*/data.gz-extract/Gemfile.lock`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemfile_lock_extracted`` - Ruby - https://bundler.io/man/gemfile.5.html * - RubyGems gemspec manifest - ``*.gemspec`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemspec`` - Ruby - https://guides.rubygems.org/specification-reference/ * - RubyGems gemspec manifest - extracted data layout - ``*/data.gz-extract/*.gemspec`` - ``gem`` + - ``linux``, ``win``, ``mac`` - ``gemspec_extracted`` - Ruby - https://guides.rubygems.org/specification-reference/ * - Go modules file - ``*/go.mod`` - ``golang`` + - ``linux``, ``win``, ``mac`` - ``go_mod`` - Go - https://go.dev/ref/mod * - Go module cheksums file - ``*/go.sum`` - ``golang`` + - ``linux``, ``win``, ``mac`` - ``go_sum`` - Go - https://go.dev/ref/mod#go-sum-files * - Go Godeps - ``*/Godeps.json`` - ``golang`` + - ``linux``, ``win``, ``mac`` - ``godeps`` - Go - https://github.com/tools/godep + * - Go binary + - None + - ``golang`` + - ``linux``, ``win``, ``mac`` + - ``golang_binary`` + - Go + - https://github.com/nexB/go-inspector/ * - Haxe haxelib.json metadata file - ``*/haxelib.json`` - ``haxe`` + - ``linux``, ``win``, ``mac`` - ``haxelib_json`` - Haxe - https://lib.haxe.org/documentation/creating-a-haxelib-package/ * - InstallShield installer - ``*.exe`` - ``installshield`` + - ``linux``, ``win``, ``mac`` - ``installshield_installer`` - None - https://www.revenera.com/install/products/installshield * - iOS package archive - ``*.ipa`` - ``ios`` + - ``linux``, ``win``, ``mac`` - ``ios_ipa`` - Objective-C - https://en.wikipedia.org/wiki/.ipa @@ -442,36 +517,42 @@ parsers in scancode-toolkit during documentation builds. ``*.udf`` ``*.img`` - ``iso`` + - ``linux``, ``win``, ``mac`` - ``iso_disk_image`` - None - https://en.wikipedia.org/wiki/ISO_9660 * - Ant IVY dependency file - ``*/ivy.xml`` - ``ivy`` + - ``linux``, ``win``, ``mac`` - ``ant_ivy_xml`` - Java - https://ant.apache.org/ivy/history/latest-milestone/ivyfile.html * - JAR Java Archive - ``*.jar`` - ``jar`` + - ``linux``, ``win``, ``mac`` - ``java_jar`` - None - https://en.wikipedia.org/wiki/JAR_(file_format) * - Java JAR MANIFEST.MF - ``*/META-INF/MANIFEST.MF`` - ``jar`` + - ``linux``, ``win``, ``mac`` - ``java_jar_manifest`` - Java - https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html * - JBOSS service archive - ``*.sar`` - ``jboss-service`` + - ``linux``, ``win``, ``mac`` - ``jboss_sar`` - Java - https://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/ch02s01.html * - JBOSS service.xml - ``*/meta-inf/jboss-service.xml`` - ``jboss-service`` + - ``linux``, ``win``, ``mac`` - ``jboss_service_xml`` - Java - https://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/ch02s01.html @@ -479,6 +560,7 @@ parsers in scancode-toolkit during documentation builds. - ``*etc/os-release`` ``*usr/lib/os-release`` - ``linux-distro`` + - ``linux``, ``win``, ``mac`` - ``etc_os_release`` - None - https://www.freedesktop.org/software/systemd/man/os-release.html @@ -486,6 +568,7 @@ parsers in scancode-toolkit during documentation builds. - ``*/build.gradle`` ``*/build.gradle.kts`` - ``maven`` + - ``linux``, ``win``, ``mac`` - ``build_gradle`` - None - None @@ -493,36 +576,42 @@ parsers in scancode-toolkit during documentation builds. - ``*.pom`` ``*pom.xml`` - ``maven`` + - ``linux``, ``win``, ``mac`` - ``maven_pom`` - Java - https://maven.apache.org/pom.html * - Apache Maven pom properties file - ``*/pom.properties`` - ``maven`` + - ``linux``, ``win``, ``mac`` - ``maven_pom_properties`` - Java - https://maven.apache.org/pom.html * - Meteor package.js - ``*/package.js`` - ``meteor`` + - ``linux``, ``win``, ``mac`` - ``meteor_package`` - JavaScript - https://docs.meteor.com/api/packagejs.html * - Mozilla XPI extension - ``*.xpi`` - ``mozilla`` + - ``linux``, ``win``, ``mac`` - ``mozilla_xpi`` - JavaScript - https://en.wikipedia.org/wiki/XPInstall * - Microsoft MSI installer - ``*.msi`` - ``msi`` + - ``linux`` - ``msi_installer`` - None - https://docs.microsoft.com/en-us/windows/win32/msi/windows-installer-portal * - npm package.json - ``*/package.json`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``npm_package_json`` - JavaScript - https://docs.npmjs.com/cli/v8/configuring-npm/package-json @@ -530,90 +619,105 @@ parsers in scancode-toolkit during documentation builds. - ``*/package-lock.json`` ``*/.package-lock.json`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``npm_package_lock_json`` - JavaScript - https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json * - npm shrinkwrap.json lockfile - ``*/npm-shrinkwrap.json`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``npm_shrinkwrap_json`` - JavaScript - https://docs.npmjs.com/cli/v8/configuring-npm/npm-shrinkwrap-json * - pnpm pnpm-lock.yaml lockfile - ``*/pnpm-lock.yaml`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``pnpm_lock_yaml`` - JavaScript - https://github.com/pnpm/spec/blob/master/lockfile/6.0.md * - pnpm shrinkwrap.yaml lockfile - ``*/shrinkwrap.yaml`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``pnpm_shrinkwrap_yaml`` - JavaScript - https://github.com/pnpm/spec/blob/master/lockfile/4.md * - pnpm workspace yaml file - ``*/pnpm-workspace.yaml`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``pnpm_workspace_yaml`` - JavaScript - https://pnpm.io/pnpm-workspace_yaml * - yarn.lock lockfile v1 format - ``*/yarn.lock`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``yarn_lock_v1`` - JavaScript - https://classic.yarnpkg.com/lang/en/docs/yarn-lock/ * - yarn.lock lockfile v2 format - ``*/yarn.lock`` - ``npm`` + - ``linux``, ``win``, ``mac`` - ``yarn_lock_v2`` - JavaScript - https://classic.yarnpkg.com/lang/en/docs/yarn-lock/ * - NSIS installer - ``*.exe`` - ``nsis`` + - ``linux``, ``win``, ``mac`` - ``nsis_installer`` - None - https://nsis.sourceforge.io/Main_Page * - NuGet nupkg package archive - ``*.nupkg`` - ``nuget`` + - ``linux``, ``win``, ``mac`` - ``nuget_nupkg`` - None - https://en.wikipedia.org/wiki/Open_Packaging_Conventions * - NuGet nuspec package manifest - ``*.nuspec`` - ``nuget`` + - ``linux``, ``win``, ``mac`` - ``nuget_nupsec`` - None - https://docs.microsoft.com/en-us/nuget/reference/nuspec * - NuGet packages.lock.json file - ``*packages.lock.json`` - ``nuget`` + - ``linux``, ``win``, ``mac`` - ``nuget_packages_lock`` - None - https://learn.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-restore * - Ocaml Opam file - ``*opam`` - ``opam`` + - ``linux``, ``win``, ``mac`` - ``opam_file`` - Ocaml - https://opam.ocaml.org/doc/Manual.html#Common-file-format * - Java OSGi MANIFEST.MF - None - ``osgi`` + - ``linux``, ``win``, ``mac`` - ``java_osgi_manifest`` - Java - https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html * - Dart pubspec lockfile - ``*pubspec.lock`` - ``pubspec`` + - ``linux``, ``win``, ``mac`` - ``pubspec_lock`` - dart - https://web.archive.org/web/20220330081004/https://gpalma.pt/blog/what-is-the-pubspec-lock/ * - Dart pubspec manifest - ``*pubspec.yaml`` - ``pubspec`` + - ``linux``, ``win``, ``mac`` - ``pubspec_yaml`` - dart - https://dart.dev/tools/pub/pubspec @@ -621,6 +725,7 @@ parsers in scancode-toolkit during documentation builds. - ``*conda.yaml`` ``*conda.yml`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``conda_yaml`` - Python - https://docs.conda.io/ @@ -634,90 +739,105 @@ parsers in scancode-toolkit during documentation builds. ``*requirements/*.in`` ``*reqs.txt`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pip_requirements`` - Python - https://pip.pypa.io/en/latest/reference/requirements-file-format/ * - Pipfile - ``*Pipfile`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pipfile`` - Python - https://github.com/pypa/pipfile * - Pipfile.lock - ``*Pipfile.lock`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pipfile_lock`` - Python - https://github.com/pypa/pipfile * - PyPI editable local installation PKG-INFO - ``*.egg-info/PKG-INFO`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_editable_egg_pkginfo`` - Python - https://peps.python.org/pep-0376/ * - PyPI egg - ``*.egg`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_egg`` - Python - https://web.archive.org/web/20210604075235/http://peak.telecommunity.com/DevCenter/PythonEggs * - PyPI extracted egg PKG-INFO - ``*/EGG-INFO/PKG-INFO`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_egg_pkginfo`` - Python - https://peps.python.org/pep-0376/ * - Python poetry pyproject.toml - ``*pip-inspect.deplock`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_inspect_deplock`` - Python - https://pip.pypa.io/en/stable/cli/pip_inspect/ * - Python poetry lockfile - ``*poetry.lock`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_poetry_lock`` - Python - https://python-poetry.org/docs/basic-usage/#installing-with-poetrylock * - Python poetry pyproject.toml - ``*pyproject.toml`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_poetry_pyproject_toml`` - Python - https://packaging.python.org/en/latest/specifications/pyproject-toml/ * - Python pyproject.toml - ``*pyproject.toml`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_pyproject_toml`` - Python - https://packaging.python.org/en/latest/specifications/pyproject-toml/ * - PyPI extracted sdist PKG-INFO - ``*/PKG-INFO`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_sdist_pkginfo`` - Python - https://peps.python.org/pep-0314/ * - Python setup.cfg - ``*setup.cfg`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_setup_cfg`` - Python - https://peps.python.org/pep-0390/ * - Python setup.py - ``*setup.py`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_setup_py`` - Python - https://docs.python.org/3.11/distutils/setupscript.html * - PyPI wheel - ``*.whl`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_wheel`` - Python - https://peps.python.org/pep-0427/ * - PyPI installed wheel METADATA - ``*.dist-info/METADATA`` - ``pypi`` + - ``linux``, ``win``, ``mac`` - ``pypi_wheel_metadata`` - Python - https://packaging.python.org/en/latest/specifications/core-metadata/ @@ -728,6 +848,7 @@ parsers in scancode-toolkit during documentation builds. ``*/README.google`` ``*/README.thirdparty`` - ``readme`` + - ``linux``, ``win``, ``mac`` - ``readme`` - None - None @@ -738,30 +859,35 @@ parsers in scancode-toolkit during documentation builds. ``*.mvl`` ``*.vip`` - ``rpm`` + - ``linux``, ``win``, ``mac`` - ``rpm_archive`` - None - https://en.wikipedia.org/wiki/RPM_Package_Manager * - RPM installed package BDB database - ``*var/lib/rpm/Packages`` - ``rpm`` + - ``linux`` - ``rpm_installed_database_bdb`` - None - https://man7.org/linux/man-pages/man8/rpmdb.8.html * - RPM installed package NDB database - ``*usr/lib/sysimage/rpm/Packages.db`` - ``rpm`` + - ``linux`` - ``rpm_installed_database_ndb`` - None - https://fedoraproject.org/wiki/Changes/NewRpmDBFormat * - RPM installed package SQLite database - ``*rpm/rpmdb.sqlite`` - ``rpm`` + - ``linux`` - ``rpm_installed_database_sqlite`` - None - https://fedoraproject.org/wiki/Changes/Sqlite_Rpmdb * - RPM mariner distroless package manifest - ``*var/lib/rpmmanifest/container-manifest-2`` - ``rpm`` + - ``linux``, ``win``, ``mac`` - ``rpm_mariner_manifest`` - None - https://github.com/microsoft/marinara/ @@ -769,24 +895,28 @@ parsers in scancode-toolkit during documentation builds. - ``*usr/share/licenses/*/COPYING*`` ``*usr/share/licenses/*/LICENSE*`` - ``rpm`` + - ``linux``, ``win``, ``mac`` - ``rpm_package_licenses`` - None - https://github.com/microsoft/marinara/ * - RPM specfile - ``*.spec`` - ``rpm`` + - ``linux``, ``win``, ``mac`` - ``rpm_spefile`` - None - https://en.wikipedia.org/wiki/RPM_Package_Manager * - shell archive - ``*.shar`` - ``shar`` + - ``linux``, ``win``, ``mac`` - ``shar_shell_archive`` - None - https://en.wikipedia.org/wiki/Shar * - Squashfs disk image - None - ``squashfs`` + - ``linux``, ``win``, ``mac`` - ``squashfs_disk_image`` - None - https://en.wikipedia.org/wiki/SquashFS @@ -794,6 +924,7 @@ parsers in scancode-toolkit during documentation builds. - ``*/Package.swift.json`` ``*/Package.swift.deplock`` - ``swift`` + - ``linux``, ``win``, ``mac`` - ``swift_package_manifest_json`` - Swift - https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html @@ -801,48 +932,56 @@ parsers in scancode-toolkit during documentation builds. - ``*/Package.resolved`` ``*/.package.resolved`` - ``swift`` + - ``linux``, ``win``, ``mac`` - ``swift_package_resolved`` - swift - https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html#package-dependency * - Swift dependency graph created by DepLock - ``*/swift-show-dependencies.deplock`` - ``swift`` + - ``linux``, ``win``, ``mac`` - ``swift_package_show_dependencies`` - Swift - https://forums.swift.org/t/swiftpm-show-dependencies-without-fetching-dependencies/51154 * - Java Web Application Archive - ``*.war`` - ``war`` + - ``linux``, ``win``, ``mac`` - ``java_war_archive`` - Java - https://en.wikipedia.org/wiki/WAR_(file_format) * - Java WAR web/xml - ``*/WEB-INF/web.xml`` - ``war`` + - ``linux``, ``win``, ``mac`` - ``java_war_web_xml`` - Java - https://en.wikipedia.org/wiki/WAR_(file_format) * - Windows Registry Installed Program - Docker SOFTWARE - ``*/Files/Windows/System32/config/SOFTWARE`` - ``windows-program`` + - ``linux`` - ``win_reg_installed_programs_docker_file_software`` - None - https://en.wikipedia.org/wiki/Windows_Registry * - Windows Registry Installed Program - Docker Software Delta - ``*/Hives/Software_Delta`` - ``windows-program`` + - ``linux`` - ``win_reg_installed_programs_docker_software_delta`` - None - https://en.wikipedia.org/wiki/Windows_Registry * - Windows Registry Installed Program - Docker UtilityVM SOFTWARE - ``*/UtilityVM/Files/Windows/System32/config/SOFTWARE`` - ``windows-program`` + - ``linux`` - ``win_reg_installed_programs_docker_utility_software`` - None - https://en.wikipedia.org/wiki/Windows_Registry * - Microsoft Update Manifest .mum file - ``*.mum`` - ``windows-update`` + - ``linux``, ``win``, ``mac`` - ``microsoft_update_manifest_mum`` - None - None @@ -865,6 +1004,8 @@ parsers in scancode-toolkit during documentation builds. ``*.tlb_*`` ``*.ocx`` - ``winexe`` + - ``linux``, ``win``, ``mac`` - ``windows_executable`` - None - https://en.wikipedia.org/wiki/Portable_Executable + \ No newline at end of file diff --git a/setup-mini.cfg b/setup-mini.cfg index cd48f30d97c..f7035feac6c 100644 --- a/setup-mini.cfg +++ b/setup-mini.cfg @@ -150,7 +150,7 @@ packages = regipy >= 3.1.0; platform_system == 'Linux' packagedcode_msitools >= 0.101.210706; platform_system == 'Linux' go-inspector >= 0.5.0; platform_system == 'Linux' - + rust-inspector >= 0.1.0; platform_system == 'Linux' [options.entry_points] console_scripts = diff --git a/setup.cfg b/setup.cfg index 8d1b28e381f..19d24c27d1b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -150,7 +150,7 @@ packages = regipy >= 3.1.0; platform_system == 'Linux' packagedcode_msitools >= 0.101.210706; platform_system == 'Linux' go-inspector >= 0.5.0; platform_system == 'Linux' - + rust-inspector >= 0.1.0; platform_system == 'Linux' [options.entry_points] console_scripts = diff --git a/src/packagedcode/__init__.py b/src/packagedcode/__init__.py index 093fd9940f7..53ada87ab09 100644 --- a/src/packagedcode/__init__.py +++ b/src/packagedcode/__init__.py @@ -251,6 +251,12 @@ except ImportError: pass +try: + from rust_inspector.packages import get_rust_binary_handler + APPLICATION_PACKAGE_DATAFILE_HANDLERS.append(get_rust_binary_handler()) +except ImportError: + pass + ALL_DATAFILE_HANDLERS = ( APPLICATION_PACKAGE_DATAFILE_HANDLERS + [ p for p in SYSTEM_PACKAGE_DATAFILE_HANDLERS diff --git a/src/packagedcode/models.py b/src/packagedcode/models.py index ae0adb95f20..64553bdbe3a 100644 --- a/src/packagedcode/models.py +++ b/src/packagedcode/models.py @@ -1043,9 +1043,9 @@ class DatafileHandler: # possible values are app, sys and info datasource_type = 'app' - # tuple of specifically supported operating systems. If None or empty, all platforms are supported - # possible values are win, mac, linux, freebsd - supported_oses = tuple() + # tuple of operating systems where getting package data using this DatafileHandler is supported. + # If None or empty, all platforms are supported, possible values are win, mac, linux, freebsd + supported_oses = ('linux', 'win', 'mac') # Sequence of known fnmatch-style case-insensitive glob patterns (e.g., Unix # shell style patterns) that apply on the whole POSIX path for package diff --git a/src/packagedcode/plugin_package.py b/src/packagedcode/plugin_package.py index b1487022c40..cd24b70bf9d 100644 --- a/src/packagedcode/plugin_package.py +++ b/src/packagedcode/plugin_package.py @@ -97,11 +97,15 @@ def get_available_package_parsers(docs=False): else: data_packages['package_type'] = cls.default_package_type data_packages['datasource_id'] = f"``{cls.datasource_id}``" + supported_oses = ', '.join(f"``{os_type}``" for os_type in cls.supported_oses) + else: path_patterns = ', '.join(repr(p) for p in cls.path_patterns) + supported_oses = ', '.join(repr(os_type) for os_type in cls.supported_oses) data_packages['package_type'] = cls.default_package_type data_packages['datasource_id'] = cls.datasource_id + data_packages['supported_oses'] = supported_oses data_packages['documentation_url'] = cls.documentation_url data_packages['default_primary_language'] = cls.default_primary_language data_packages['description'] = cls.description diff --git a/src/packagedcode/templates/available_package_parsers.rst b/src/packagedcode/templates/available_package_parsers.rst index 6b34e70aeaa..bb1c3999139 100644 --- a/src/packagedcode/templates/available_package_parsers.rst +++ b/src/packagedcode/templates/available_package_parsers.rst @@ -20,6 +20,7 @@ parsers in scancode-toolkit during documentation builds. * - Description - Path Patterns - Package type + - Supported OS for detection - Datasource ID - Primary Language - Documentation URL @@ -27,6 +28,7 @@ parsers in scancode-toolkit during documentation builds. * - {% if package_data.description %}{{ package_data.description }}{% else %}{{"None"}}{% endif %} - {% if package_data.path_patterns %}{{ package_data.path_patterns }}{% else %}{{"None"}}{% endif %} - {{ package_data.package_type }} + - {{ package_data.supported_oses }} - {{ package_data.datasource_id }} - {{ package_data.default_primary_language }} - {% if package_data.documentation_url %}{{ package_data.documentation_url }}{% else %}{{"None"}}{% endif %} From 330ce342f9bc59d764ddd38c4afa639dfd97cd46 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 30 Dec 2024 11:11:38 +0530 Subject: [PATCH 09/29] Add rust binary parsing test Signed-off-by: Ayan Sinha Mahapatra --- .../cargo/binary/cargo-binary.expected.json | 1743 +++++++++++++++++ .../data/cargo/binary/cargo_dependencies | Bin 0 -> 420072 bytes tests/packagedcode/test_cargo.py | 9 + 3 files changed, 1752 insertions(+) create mode 100644 tests/packagedcode/data/cargo/binary/cargo-binary.expected.json create mode 100755 tests/packagedcode/data/cargo/binary/cargo_dependencies diff --git a/tests/packagedcode/data/cargo/binary/cargo-binary.expected.json b/tests/packagedcode/data/cargo/binary/cargo-binary.expected.json new file mode 100644 index 00000000000..6fe0a7d75bd --- /dev/null +++ b/tests/packagedcode/data/cargo/binary/cargo-binary.expected.json @@ -0,0 +1,1743 @@ +{ + "packages": [ + { + "type": "cargo", + "namespace": null, + "name": "aho-corasick", + "version": "0.5.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/aho-corasick", + "repository_download_url": "https://crates.io/api/v1/crates/aho-corasick/0.5.3/download", + "api_data_url": "https://crates.io/api/v1/crates/aho-corasick", + "package_uid": "pkg:cargo/aho-corasick@0.5.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/aho-corasick@0.5.3" + }, + { + "type": "cargo", + "namespace": null, + "name": "bitflags", + "version": "2.6.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/bitflags", + "repository_download_url": "https://crates.io/api/v1/crates/bitflags/2.6.0/download", + "api_data_url": "https://crates.io/api/v1/crates/bitflags", + "package_uid": "pkg:cargo/bitflags@2.6.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/bitflags@2.6.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "cargo_dependencies", + "version": "0.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": true, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "package_uid": "pkg:cargo/cargo_dependencies@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/cargo_dependencies@0.1.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "kernel32-sys", + "version": "0.2.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/kernel32-sys", + "repository_download_url": "https://crates.io/api/v1/crates/kernel32-sys/0.2.2/download", + "api_data_url": "https://crates.io/api/v1/crates/kernel32-sys", + "package_uid": "pkg:cargo/kernel32-sys@0.2.2?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/kernel32-sys@0.2.2" + }, + { + "type": "cargo", + "namespace": null, + "name": "libc", + "version": "0.2.167", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/libc", + "repository_download_url": "https://crates.io/api/v1/crates/libc/0.2.167/download", + "api_data_url": "https://crates.io/api/v1/crates/libc", + "package_uid": "pkg:cargo/libc@0.2.167?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/libc@0.2.167" + }, + { + "type": "cargo", + "namespace": null, + "name": "memchr", + "version": "0.1.11", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/memchr", + "repository_download_url": "https://crates.io/api/v1/crates/memchr/0.1.11/download", + "api_data_url": "https://crates.io/api/v1/crates/memchr", + "package_uid": "pkg:cargo/memchr@0.1.11?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/memchr@0.1.11" + }, + { + "type": "cargo", + "namespace": null, + "name": "regex", + "version": "0.1.80", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/regex", + "repository_download_url": "https://crates.io/api/v1/crates/regex/0.1.80/download", + "api_data_url": "https://crates.io/api/v1/crates/regex", + "package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/regex@0.1.80" + }, + { + "type": "cargo", + "namespace": null, + "name": "regex-syntax", + "version": "0.3.9", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/regex-syntax", + "repository_download_url": "https://crates.io/api/v1/crates/regex-syntax/0.3.9/download", + "api_data_url": "https://crates.io/api/v1/crates/regex-syntax", + "package_uid": "pkg:cargo/regex-syntax@0.3.9?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/regex-syntax@0.3.9" + }, + { + "type": "cargo", + "namespace": null, + "name": "thread-id", + "version": "2.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/thread-id", + "repository_download_url": "https://crates.io/api/v1/crates/thread-id/2.0.0/download", + "api_data_url": "https://crates.io/api/v1/crates/thread-id", + "package_uid": "pkg:cargo/thread-id@2.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/thread-id@2.0.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "thread_local", + "version": "0.2.7", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/thread_local", + "repository_download_url": "https://crates.io/api/v1/crates/thread_local/0.2.7/download", + "api_data_url": "https://crates.io/api/v1/crates/thread_local", + "package_uid": "pkg:cargo/thread_local@0.2.7?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/thread_local@0.2.7" + }, + { + "type": "cargo", + "namespace": null, + "name": "time", + "version": "0.1.45", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/time", + "repository_download_url": "https://crates.io/api/v1/crates/time/0.1.45/download", + "api_data_url": "https://crates.io/api/v1/crates/time", + "package_uid": "pkg:cargo/time@0.1.45?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/time@0.1.45" + }, + { + "type": "cargo", + "namespace": null, + "name": "utf8-ranges", + "version": "0.1.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/utf8-ranges", + "repository_download_url": "https://crates.io/api/v1/crates/utf8-ranges/0.1.3/download", + "api_data_url": "https://crates.io/api/v1/crates/utf8-ranges", + "package_uid": "pkg:cargo/utf8-ranges@0.1.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/utf8-ranges@0.1.3" + }, + { + "type": "cargo", + "namespace": null, + "name": "winapi", + "version": "0.2.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/winapi", + "repository_download_url": "https://crates.io/api/v1/crates/winapi/0.2.8/download", + "api_data_url": "https://crates.io/api/v1/crates/winapi", + "package_uid": "pkg:cargo/winapi@0.2.8?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/winapi@0.2.8" + }, + { + "type": "cargo", + "namespace": null, + "name": "winapi-build", + "version": "0.1.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "repository_homepage_url": "https://crates.io/crates/winapi-build", + "repository_download_url": "https://crates.io/api/v1/crates/winapi-build/0.1.1/download", + "api_data_url": "https://crates.io/api/v1/crates/winapi-build", + "package_uid": "pkg:cargo/winapi-build@0.1.1?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "cargo_dependencies" + ], + "datasource_ids": [ + "rust_binary" + ], + "purl": "pkg:cargo/winapi-build@0.1.1" + } + ], + "dependencies": [ + { + "purl": "pkg:cargo/memchr@0.1.11", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/memchr@0.1.11?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/aho-corasick@0.5.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/bitflags@2.6.0", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/bitflags@2.6.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/cargo_dependencies@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/regex@0.1.80", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/cargo_dependencies@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/time@0.1.45", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/time@0.1.45?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/cargo_dependencies@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/winapi@0.2.8", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/winapi@0.2.8?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/kernel32-sys@0.2.2?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/winapi-build@0.1.1", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/winapi-build@0.1.1?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/kernel32-sys@0.2.2?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/libc@0.2.167?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/memchr@0.1.11?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/aho-corasick@0.5.3", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/aho-corasick@0.5.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/memchr@0.1.11", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/memchr@0.1.11?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/regex-syntax@0.3.9", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/regex-syntax@0.3.9?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/thread_local@0.2.7", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/thread_local@0.2.7?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/utf8-ranges@0.1.3", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/utf8-ranges@0.1.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/kernel32-sys@0.2.2", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/kernel32-sys@0.2.2?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/thread-id@2.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/libc@0.2.167?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/thread-id@2.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/thread-id@2.0.0", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/thread-id@2.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/thread_local@0.2.7?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + }, + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:cargo/libc@0.2.167?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:cargo/time@0.1.45?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "cargo_dependencies", + "datasource_id": "rust_binary" + } + ], + "files": [ + { + "path": "cargo_dependencies", + "type": "file", + "package_data": [ + { + "type": "cargo", + "namespace": null, + "name": "aho-corasick", + "version": "0.5.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/memchr@0.1.11", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/aho-corasick", + "repository_download_url": "https://crates.io/api/v1/crates/aho-corasick/0.5.3/download", + "api_data_url": "https://crates.io/api/v1/crates/aho-corasick", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/aho-corasick@0.5.3" + }, + { + "type": "cargo", + "namespace": null, + "name": "bitflags", + "version": "2.6.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/bitflags", + "repository_download_url": "https://crates.io/api/v1/crates/bitflags/2.6.0/download", + "api_data_url": "https://crates.io/api/v1/crates/bitflags", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/bitflags@2.6.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "cargo_dependencies", + "version": "0.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": true, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/bitflags@2.6.0", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/regex@0.1.80", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/time@0.1.45", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "rust_binary", + "purl": "pkg:cargo/cargo_dependencies@0.1.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "kernel32-sys", + "version": "0.2.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/winapi@0.2.8", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/winapi-build@0.1.1", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/kernel32-sys", + "repository_download_url": "https://crates.io/api/v1/crates/kernel32-sys/0.2.2/download", + "api_data_url": "https://crates.io/api/v1/crates/kernel32-sys", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/kernel32-sys@0.2.2" + }, + { + "type": "cargo", + "namespace": null, + "name": "libc", + "version": "0.2.167", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/libc", + "repository_download_url": "https://crates.io/api/v1/crates/libc/0.2.167/download", + "api_data_url": "https://crates.io/api/v1/crates/libc", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/libc@0.2.167" + }, + { + "type": "cargo", + "namespace": null, + "name": "memchr", + "version": "0.1.11", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/memchr", + "repository_download_url": "https://crates.io/api/v1/crates/memchr/0.1.11/download", + "api_data_url": "https://crates.io/api/v1/crates/memchr", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/memchr@0.1.11" + }, + { + "type": "cargo", + "namespace": null, + "name": "regex", + "version": "0.1.80", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/aho-corasick@0.5.3", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/memchr@0.1.11", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/regex-syntax@0.3.9", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/thread_local@0.2.7", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/utf8-ranges@0.1.3", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/regex", + "repository_download_url": "https://crates.io/api/v1/crates/regex/0.1.80/download", + "api_data_url": "https://crates.io/api/v1/crates/regex", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/regex@0.1.80" + }, + { + "type": "cargo", + "namespace": null, + "name": "regex-syntax", + "version": "0.3.9", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/regex-syntax", + "repository_download_url": "https://crates.io/api/v1/crates/regex-syntax/0.3.9/download", + "api_data_url": "https://crates.io/api/v1/crates/regex-syntax", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/regex-syntax@0.3.9" + }, + { + "type": "cargo", + "namespace": null, + "name": "thread-id", + "version": "2.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/kernel32-sys@0.2.2", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/thread-id", + "repository_download_url": "https://crates.io/api/v1/crates/thread-id/2.0.0/download", + "api_data_url": "https://crates.io/api/v1/crates/thread-id", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/thread-id@2.0.0" + }, + { + "type": "cargo", + "namespace": null, + "name": "thread_local", + "version": "0.2.7", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/thread-id@2.0.0", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/thread_local", + "repository_download_url": "https://crates.io/api/v1/crates/thread_local/0.2.7/download", + "api_data_url": "https://crates.io/api/v1/crates/thread_local", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/thread_local@0.2.7" + }, + { + "type": "cargo", + "namespace": null, + "name": "time", + "version": "0.1.45", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:cargo/libc@0.2.167", + "extracted_requirement": null, + "scope": "build-dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://crates.io/crates/time", + "repository_download_url": "https://crates.io/api/v1/crates/time/0.1.45/download", + "api_data_url": "https://crates.io/api/v1/crates/time", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/time@0.1.45" + }, + { + "type": "cargo", + "namespace": null, + "name": "utf8-ranges", + "version": "0.1.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/utf8-ranges", + "repository_download_url": "https://crates.io/api/v1/crates/utf8-ranges/0.1.3/download", + "api_data_url": "https://crates.io/api/v1/crates/utf8-ranges", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/utf8-ranges@0.1.3" + }, + { + "type": "cargo", + "namespace": null, + "name": "winapi", + "version": "0.2.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/winapi", + "repository_download_url": "https://crates.io/api/v1/crates/winapi/0.2.8/download", + "api_data_url": "https://crates.io/api/v1/crates/winapi", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/winapi@0.2.8" + }, + { + "type": "cargo", + "namespace": null, + "name": "winapi-build", + "version": "0.1.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "Rust", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://crates.io/crates/winapi-build", + "repository_download_url": "https://crates.io/api/v1/crates/winapi-build/0.1.1/download", + "api_data_url": "https://crates.io/api/v1/crates/winapi-build", + "datasource_id": "rust_binary", + "purl": "pkg:cargo/winapi-build@0.1.1" + } + ], + "for_packages": [ + "pkg:cargo/aho-corasick@0.5.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/bitflags@2.6.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/cargo_dependencies@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/kernel32-sys@0.2.2?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/libc@0.2.167?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/memchr@0.1.11?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/regex@0.1.80?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/regex-syntax@0.3.9?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/thread-id@2.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/thread_local@0.2.7?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/time@0.1.45?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/utf8-ranges@0.1.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/winapi@0.2.8?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:cargo/winapi-build@0.1.1?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/packagedcode/data/cargo/binary/cargo_dependencies b/tests/packagedcode/data/cargo/binary/cargo_dependencies new file mode 100755 index 0000000000000000000000000000000000000000..944e13d8d4a09c3fb33c18f501a0236956b34d4d GIT binary patch literal 420072 zcmeFa3w%`7xi>tM3kd@5K^YBd>r_F(Yoefu0hvGs_J%zW6$CFx5Q9*;q{$4#T1sGo zWS`yXNv*c@cAB1ZdP-02+w`XKKH-uCR1A0_YO4V)P8=@-DnwA``#)=~J+o(#?Xl2uKkHe~de(DUm!0(ieR_`D?XrGyUDvzls&yGh{Nl#A>LKEr%jI{K zx=zRM3tbnu2+hNPzql)ZdUE*<>$6alBbc7668GiL^F%r8)8ddm={cvL*c^Vx`gD2t zH9eP4U#s}F{Q2nsXTEKrGg*9 zXAUmux#sD-eDlrOpB^fJAM4YSCvivrYlS@JPap2lkB|L!x#Z_s#B=gzr6_NGQXTYD zfdBN}seL}&qn~Q_J5%3He+%73&&m8**FI6+`n34063@N;bIyVM`7MP%Xnk6I-hk&w zo?rGybc5?gQJ+)$mWlqeJ}v#ca>epHubFV=in}gfv3ymy;qr#kYc9WL!WH$auege_ zKzvah)T=XQ&vWH8x?+S`&(rr&_)pzI_kXePwLcuWXSjF7rQz2O|90fhH$3-^{-db4gULILEwx*ZWTG;We)iN0t185+2v54 zS~FOA9~w9qPVMsz!so{h^xty8BOr9aAatH{;J?Iyp9K!(+dz9T{%>?B?{mOUIMCVP z(60Y0D1Wy@`Be_(r#tXj;UNF(9PrZ|=yy2aH#*>70slVy zmw$fgz~>7NbY2F5!Stcoq5Mh*`e!(_ca}r>d`JXzJf6SqL(xH5j1OLBvpc8VSa~b60!+-hbEdYb*Nz8%H zbcgcSJMh!xQ2tubzd&Y&t`})@gNyE}sjInrd3~s+ZfccDXoVc92c*#AXy2VQ}$c&nhzIfH$;l+2? z+*Dh$WckwNODY$K7N?)UeXUAcwRE)|p%ORNteCpEK8w(eV0rbbn~1q|>6_^J^cAC) zzN)NQQ4^{OG%Ts94dKBwe&gch^@G45HRHx~A&{C|(-2Ctv1m!d;zdiBuUfof`8R7^ zbv29ca;;pvV#VquuC;Z`Lp83YOIC$exK`GzT)BEpjca9i)yl=Su9f(8%>-BN>iXpk zi*OGQ-wi$(t}4&8Wj8i)xqMRYxtUuL-&Ct_dv;H>^RqrFAtKYPeM|x-+{5 zl;^xHS+N?uXVp#&-Nm}Y1rAo!tV-WueBmjmNZnoaBwJk6tXkt*3OXS$MzSC=*WX*e zWc8}0>=TG<@tv!o2Viqa?Y(Jg^))L{0wP+%dK{#dti3CJ7niKMRki36kf0hGT(yhC z;B-ZOP0c;1ZqXtLbJglasB$r*LA``f@E+F^&c~ufp%wLuKx)zAyC5g@&)rMVLlhyF z(A5(9c8zP$0CI+|O`W#rsw=K`&6qZA(S$3mx}unUyE^@eJEF{0rRlFF*JQpWYal13BzpE`I0XzZ>yv4&uxLh8E&?A^zpKh9WMdlBY3* zz7J#9Il$en;jR%V#Y=E{Imjy&_9Q)R|2Gs@ZgD4vMu&Rsh9Y)#7_r�>^jf&qxAEqx$Y46h+gyeet>XV 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
+8i7JN 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', ('Barney Rubble ', '')), From 7f2df4df1ede478dd1d4c2539c5114acd4436d28 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 30 Dec 2024 12:43:56 +0530 Subject: [PATCH 10/29] Fix sphinx build and CI tests Signed-off-by: Ayan Sinha Mahapatra --- docs/source/reference/available_package_parsers.rst | 10 ++++++++-- setup-mini.cfg | 2 +- setup.cfg | 2 +- src/packagedcode/models.py | 2 +- src/packagedcode/plugin_package.py | 9 +++++++-- .../templates/available_package_parsers.rst | 2 +- tests/packagedcode/data/plugin/plugins_list_linux.txt | 7 +++++++ tests/scancode/data/help/help_linux.txt | 1 + tests/scancode/test_cli.py | 2 +- 9 files changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/source/reference/available_package_parsers.rst b/docs/source/reference/available_package_parsers.rst index d97f897020d..ca35c9c2acd 100644 --- a/docs/source/reference/available_package_parsers.rst +++ b/docs/source/reference/available_package_parsers.rst @@ -14,7 +14,7 @@ parsers in scancode-toolkit during documentation builds. .. list-table:: Supported Package Parsers - :widths: 10 10 20 10 10 2 + :widths: 10 10 20 10 10 10 2 :header-rows: 1 * - Description @@ -140,6 +140,13 @@ parsers in scancode-toolkit during documentation builds. - ``cargo_toml`` - Rust - https://doc.rust-lang.org/cargo/reference/manifest.html + * - Rust binary + - None + - ``cargo`` + - ``linux``, ``win``, ``mac`` + - ``rust_binary`` + - Rust + - https://github.com/rust-secure-code/cargo-auditable/blob/master/PARSING.md * - Chef cookbook metadata.json - ``*/metadata.json`` - ``chef`` @@ -1008,4 +1015,3 @@ parsers in scancode-toolkit during documentation builds. - ``windows_executable`` - None - https://en.wikipedia.org/wiki/Portable_Executable - \ No newline at end of file diff --git a/setup-mini.cfg b/setup-mini.cfg index f7035feac6c..790faa1187e 100644 --- a/setup-mini.cfg +++ b/setup-mini.cfg @@ -67,7 +67,7 @@ install_requires = Beautifulsoup4 >= 4.0.0 boolean.py >= 4.0 chardet >= 3.0.0 - click >= 6.7, !=7.0 + click >= 6.7, !=7.0, !=8.1.8 colorama >= 0.3.9 commoncode >= 32.0.0 container-inspector >= 31.0.0 diff --git a/setup.cfg b/setup.cfg index 19d24c27d1b..797f40bc4f9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -67,7 +67,7 @@ install_requires = Beautifulsoup4 >= 4.0.0 boolean.py >= 4.0 chardet >= 3.0.0 - click >= 6.7, !=7.0 + click >= 6.7, !=7.0, !=8.1.8 colorama >= 0.3.9 commoncode >= 32.0.0 container-inspector >= 31.0.0 diff --git a/src/packagedcode/models.py b/src/packagedcode/models.py index 64553bdbe3a..40fa8bb3e93 100644 --- a/src/packagedcode/models.py +++ b/src/packagedcode/models.py @@ -1045,7 +1045,7 @@ class DatafileHandler: # tuple of operating systems where getting package data using this DatafileHandler is supported. # If None or empty, all platforms are supported, possible values are win, mac, linux, freebsd - supported_oses = ('linux', 'win', 'mac') + supported_oses = None # Sequence of known fnmatch-style case-insensitive glob patterns (e.g., Unix # shell style patterns) that apply on the whole POSIX path for package diff --git a/src/packagedcode/plugin_package.py b/src/packagedcode/plugin_package.py index cd24b70bf9d..252d6cb1dd4 100644 --- a/src/packagedcode/plugin_package.py +++ b/src/packagedcode/plugin_package.py @@ -89,6 +89,11 @@ def get_available_package_parsers(docs=False): if cls.datasource_id is None: raise Exception(cls) + if not cls.supported_oses: + supported_oses = ('linux', 'win', 'mac') + else: + supported_oses = cls.supported_oses + data_packages = {} if docs: path_patterns = '\n '.join(f"``{p}``" for p in cls.path_patterns) @@ -97,11 +102,11 @@ def get_available_package_parsers(docs=False): else: data_packages['package_type'] = cls.default_package_type data_packages['datasource_id'] = f"``{cls.datasource_id}``" - supported_oses = ', '.join(f"``{os_type}``" for os_type in cls.supported_oses) + supported_oses = ', '.join(f"``{os_type}``" for os_type in supported_oses) else: path_patterns = ', '.join(repr(p) for p in cls.path_patterns) - supported_oses = ', '.join(repr(os_type) for os_type in cls.supported_oses) + supported_oses = ', '.join(repr(os_type) for os_type in supported_oses) data_packages['package_type'] = cls.default_package_type data_packages['datasource_id'] = cls.datasource_id diff --git a/src/packagedcode/templates/available_package_parsers.rst b/src/packagedcode/templates/available_package_parsers.rst index bb1c3999139..b5a3a3e1a53 100644 --- a/src/packagedcode/templates/available_package_parsers.rst +++ b/src/packagedcode/templates/available_package_parsers.rst @@ -14,7 +14,7 @@ parsers in scancode-toolkit during documentation builds. .. list-table:: Supported Package Parsers - :widths: 10 10 20 10 10 2 + :widths: 10 10 20 10 10 10 2 :header-rows: 1 * - Description diff --git a/tests/packagedcode/data/plugin/plugins_list_linux.txt b/tests/packagedcode/data/plugin/plugins_list_linux.txt index 45585388487..9468fab2cc4 100755 --- a/tests/packagedcode/data/plugin/plugins_list_linux.txt +++ b/tests/packagedcode/data/plugin/plugins_list_linux.txt @@ -111,6 +111,13 @@ Package type: cargo description: Rust Cargo.toml package manifest path_patterns: '*/Cargo.toml', '*/cargo.toml' -------------------------------------------- +Package type: cargo + datasource_id: rust_binary + documentation URL: https://github.com/rust-secure-code/cargo-auditable/blob/master/PARSING.md + primary language: Rust + description: Rust binary + path_patterns: +-------------------------------------------- Package type: chef datasource_id: chef_cookbook_metadata_json documentation URL: https://docs.chef.io/config_rb_metadata/ diff --git a/tests/scancode/data/help/help_linux.txt b/tests/scancode/data/help/help_linux.txt index 1295e3c4745..a6527a51f3d 100644 --- a/tests/scancode/data/help/help_linux.txt +++ b/tests/scancode/data/help/help_linux.txt @@ -16,6 +16,7 @@ Options: license/copyright detection and top-level package creation. -c, --copyright Scan for copyrights. --go-symbol Collect Go symbols. + --rust-symbol Collect Rust symbols from rust binaries. other scans: -i, --info Scan for file information (size, checksums, etc). diff --git a/tests/scancode/test_cli.py b/tests/scancode/test_cli.py index e537002af6c..c1edea6604a 100644 --- a/tests/scancode/test_cli.py +++ b/tests/scancode/test_cli.py @@ -128,7 +128,7 @@ def test_no_version_check_run_is_successful(): def test_usage_and_help_return_a_correct_script_name_on_all_platforms(): - result = run_scan_click(['--help']) + result = run_scan_click(options=['--help'], test_mode=False, retry=False) assert 'Usage: scancode [OPTIONS]' in result.output # this was showing up on Windows assert 'scancode-script.py' not in result.output From c59de73627d8f92128930e089091c889810489da Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 16:34:36 +0530 Subject: [PATCH 11/29] Do not fail scan or assembly for invalid package.json Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/npm.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/packagedcode/npm.py b/src/packagedcode/npm.py index f2a8aff6bcb..6081f489d17 100644 --- a/src/packagedcode/npm.py +++ b/src/packagedcode/npm.py @@ -114,6 +114,10 @@ def assemble(cls, package_data, resource, codebase, package_adder): yield from models.DatafileHandler.assemble(package_data, resource, codebase, package_adder) return + # We do not have any package data detected here + if not package_resource.package_data: + return + assert len(package_resource.package_data) == 1, f'Invalid package.json for {package_resource.path}' pkg_data = package_resource.package_data[0] pkg_data = models.PackageData.from_dict(pkg_data) From a98327e5ef97ea08c34a4977df59514e4c79a416 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 13:02:16 +0530 Subject: [PATCH 12/29] Improve conda packages and dependencies parsing Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/__init__.py | 2 +- src/packagedcode/conda.py | 176 +++- src/packagedcode/models.py | 11 +- .../conda-yaml/phc-gnn/environment_gpu.yml | 40 + .../phc-gnn/environment_gpu.yml-expected.json | 285 ++++++ .../conda/conda-yaml/ringer/environment.yaml | 27 + .../ringer/environment.yaml-expected.json | 240 +++++ .../conda/{ => meta-yaml/abeona}/meta.yaml | 0 .../abeona/meta.yaml-expected.json} | 51 +- .../data/conda/meta-yaml/gcnvkernel/meta.yaml | 68 ++ .../gcnvkernel/meta.yaml-expected.json | 364 +++++++ .../data/conda/meta-yaml/pippy/meta.yaml | 26 + .../meta-yaml/pippy/meta.yaml-expected.json | 164 ++++ .../meta-yaml/pippy/meta.yaml-scancode.json | 383 ++++++++ .../data/misc/conda/scenicplus.yaml | 101 ++ .../misc/conda/scenicplus.yaml-expected.json | 921 ++++++++++++++++++ .../data/plugin/conda-package-expected.json | 134 +-- .../data/plugin/plugins_list_linux.txt | 14 +- tests/packagedcode/test_conda.py | 80 +- 19 files changed, 2931 insertions(+), 156 deletions(-) create mode 100644 tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml create mode 100644 tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json create mode 100644 tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml create mode 100644 tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json rename tests/packagedcode/data/conda/{ => meta-yaml/abeona}/meta.yaml (100%) rename tests/packagedcode/data/conda/{meta.yaml.expected.json => meta-yaml/abeona/meta.yaml-expected.json} (80%) create mode 100644 tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml create mode 100644 tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml-expected.json create mode 100644 tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml create mode 100644 tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-expected.json create mode 100644 tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json create mode 100644 tests/packagedcode/data/misc/conda/scenicplus.yaml create mode 100644 tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json diff --git a/src/packagedcode/__init__.py b/src/packagedcode/__init__.py index 53ada87ab09..778d0434922 100644 --- a/src/packagedcode/__init__.py +++ b/src/packagedcode/__init__.py @@ -73,8 +73,8 @@ cocoapods.PodfileLockHandler, cocoapods.PodfileHandler, - conda.CondaYamlHandler, conda.CondaMetaYamlHandler, + conda.CondaYamlHandler, conan.ConanFileHandler, conan.ConanDataHandler, diff --git a/src/packagedcode/conda.py b/src/packagedcode/conda.py index 225940d69fc..80b71cbb12b 100644 --- a/src/packagedcode/conda.py +++ b/src/packagedcode/conda.py @@ -14,6 +14,7 @@ from packagedcode import models from packagedcode.pypi import BaseDependencyFileHandler +from dparse2.parser import parse_requirement_line """ Handle Conda manifests and metadata, see https://docs.conda.io/en/latest/ @@ -23,18 +24,36 @@ """ # TODO: there are likely other package data files for Conda -# TODO: report platform - class CondaYamlHandler(BaseDependencyFileHandler): - # TODO: there are several other manifests worth adding datasource_id = 'conda_yaml' - path_patterns = ('*conda.yaml', '*conda.yml',) - default_package_type = 'pypi' + path_patterns = ('*conda*.yaml', '*env*.yaml', '*environment*.yaml') + default_package_type = 'conda' default_primary_language = 'Python' description = 'Conda yaml manifest' documentation_url = 'https://docs.conda.io/' + @classmethod + def parse(cls, location, package_only=False): + with open(location) as fi: + conda_data = saneyaml.load(fi.read()) + dependencies = get_conda_yaml_dependencies(conda_data=conda_data) + name = conda_data.get('name') + extra_data = {} + channels = conda_data.get('channels') + if channels: + extra_data['channels'] = channels + if name or dependencies: + package_data = dict( + datasource_id=cls.datasource_id, + type=cls.default_package_type, + name=name, + primary_language=cls.default_primary_language, + dependencies=dependencies, + extra_data=extra_data, + ) + yield models.PackageData.from_data(package_data, package_only) + class CondaMetaYamlHandler(models.DatafileHandler): datasource_id = 'conda_meta_yaml' @@ -83,9 +102,7 @@ def parse(cls, location, package_only=False): metayaml = get_meta_yaml_data(location) package_element = metayaml.get('package') or {} package_name = package_element.get('name') - if not package_name: - return - version = package_element.get('version') + package_version = package_element.get('version') # FIXME: source is source, not download source = metayaml.get('source') or {} @@ -99,6 +116,7 @@ def parse(cls, location, package_only=False): vcs_url = about.get('dev_url') dependencies = [] + extra_data = {} requirements = metayaml.get('requirements') or {} for scope, reqs in requirements.items(): # requirements format is like: @@ -107,14 +125,51 @@ def parse(cls, location, package_only=False): # u'progressbar2', u'python >=3.6'])]) for req in reqs: name, _, requirement = req.partition(" ") - purl = PackageURL(type=cls.default_package_type, name=name) + version = None + if requirement.startswith("=="): + _, version = requirement.split("==") + + # requirements may have namespace, version too + # - conda-forge::numpy=1.15.4 + namespace = None + if "::" in name: + namespace, name = name.split("::") + + is_pinned = False + if "=" in name: + name, version = name.split("=") + is_pinned = True + requirement = f"={version}" + + if name in ('pip', 'python'): + if not scope in extra_data: + extra_data[scope] = [req] + else: + extra_data[scope].append(req) + continue + + purl = PackageURL( + type=cls.default_package_type, + name=name, + namespace=namespace, + version=version, + ) + if "run" in scope: + is_runtime = True + is_optional = False + else: + is_runtime = False + is_optional = True + dependencies.append( models.DependentPackage( purl=purl.to_string(), extracted_requirement=requirement, scope=scope, - is_runtime=True, - is_optional=False, + is_runtime=is_runtime, + is_optional=is_optional, + is_pinned=is_pinned, + is_direct=True, ) ) @@ -122,7 +177,7 @@ def parse(cls, location, package_only=False): datasource_id=cls.datasource_id, type=cls.default_package_type, name=package_name, - version=version, + version=package_version, download_url=download_url, homepage_url=homepage_url, vcs_url=vcs_url, @@ -130,10 +185,92 @@ def parse(cls, location, package_only=False): sha256=sha256, extracted_license_statement=extracted_license_statement, dependencies=dependencies, + extra_data=extra_data, ) yield models.PackageData.from_data(package_data, package_only) +def get_conda_yaml_dependencies(conda_data): + """ + Return a list of DependentPackage mappins from conda and pypi + dependencies present in a `conda_data` mapping. + """ + dependencies = conda_data.get('dependencies') or [] + deps = [] + for dep in dependencies: + if isinstance(dep, str): + namespace = None + specs = None + is_pinned = False + + if "::" in dep: + namespace, dep = dep.split("::") + + req = parse_requirement_line(dep) + if req: + name = req.name + version = None + + specs = str(req.specs) + if '==' in specs: + version = specs.replace('==','') + is_pinned = True + purl = PackageURL(type='pypi', name=name, version=version) + else: + if "=" in dep: + dep, version = dep.split("=") + is_pinned = True + specs = f"={version}" + + purl = PackageURL( + type='conda', + namespace=namespace, + name=dep, + version=version, + ) + + if purl.name in ('pip', 'python'): + continue + + deps.append( + models.DependentPackage( + purl=purl.to_string(), + extracted_requirement=specs, + scope='dependencies', + is_runtime=True, + is_optional=False, + is_pinned=is_pinned, + is_direct=True, + ).to_dict() + ) + + elif isinstance(dep, dict): + for line in dep.get('pip', []): + req = parse_requirement_line(line) + if req: + name = req.name + version = None + is_pinned = False + specs = str(req.specs) + if '==' in specs: + version = specs.replace('==','') + is_pinned = True + purl = PackageURL(type='pypi', name=name, version=version) + deps.append( + models.DependentPackage( + purl=purl.to_string(), + extracted_requirement=specs, + scope='dependencies', + is_runtime=True, + is_optional=False, + is_pinned=is_pinned, + is_direct=True, + ).to_dict() + ) + + return deps + + def get_meta_yaml_data(location): """ Return a mapping of conda metadata loaded from a meta.yaml files. The format @@ -158,10 +295,21 @@ def get_meta_yaml_data(location): # Replace the variable with the value if '{{' in line and '}}' in line: for variable, value in variables.items(): - line = line.replace('{{ ' + variable + ' }}', value) + if "|lower" in line: + line = line.replace('{{ ' + variable + '|lower' + ' }}', value.lower()) + else: + line = line.replace('{{ ' + variable + ' }}', value) yaml_lines.append(line) - return saneyaml.load('\n'.join(yaml_lines)) + # Cleanup any remaining complex jinja template lines + # as the yaml load fails otherwise for unresolved jinja + cleaned_yaml_lines = [ + line + for line in yaml_lines + if not "{{" in line + ] + + return saneyaml.load(''.join(cleaned_yaml_lines)) def get_variables(location): diff --git a/src/packagedcode/models.py b/src/packagedcode/models.py index 40fa8bb3e93..d518c73330d 100644 --- a/src/packagedcode/models.py +++ b/src/packagedcode/models.py @@ -1100,7 +1100,16 @@ def is_datafile(cls, location, filetypes=tuple(), _bare_filename=False): """ if filetype.is_file(location) or _bare_filename: loc = as_posixpath(location) - if any(fnmatchcase(loc, pat) for pat in cls.path_patterns): + + # Some extension strings are used interchangebly + extension_aliases = {"yaml": "yml"} + path_patterns = list(cls.path_patterns) + for pattern in cls.path_patterns: + for extension, extension_alias in extension_aliases.items(): + new_pattern = pattern.replace(extension, extension_alias) + path_patterns.append(new_pattern) + + if any(fnmatchcase(loc, pat) for pat in path_patterns): filetypes = filetypes or cls.filetypes if not filetypes: return True diff --git a/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml new file mode 100644 index 00000000000..312ca4b8fbe --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml @@ -0,0 +1,40 @@ +# from https://raw.githubusercontent.com/bayer-science-for-a-better-life/phc-gnn/refs/heads/master/environment_gpu.yml + +name: phc-gnn + +channels: + - anaconda + - pytorch + - conda-forge + - defaults + +dependencies: + - pip=20.2.4 + - anaconda::python=3.8.5 + - anaconda::python-dateutil=2.8.1 + - cudatoolkit=10.1 + - magma-cuda101 + - cudnn=7.6.5 + - pytorch=1.7.1 + - torchvision=0.8.2 + - torchaudio=0.7.2 + - conda-forge::numpy=1.19.2 + - anaconda::scipy=1.5.2 + - conda-forge::matplotlib=3.3.2 + - anaconda::networkx=2.5 + - anaconda::scikit-learn=0.23.2 + - anaconda::notebook=6.1.4 + - anaconda::jupyter_client=6.1.7 + - anaconda::jupyter_core=4.6.3 + - anaconda::h5py=2.10.0 + - conda-forge::tqdm=4.50.0 + - conda-forge::tensorboard=2.4.0 + - pip: + - ogb==1.2.4 + - pytest==6.2.1 + - bottleneck==1.3.2 + # - torch-cluster==1.5.8 + # - torch-scatter==2.0.5 + # - torch-sparse==0.6.8 + # - torch-spline-conv==1.2.0 + # - torch-geometric==1.6.1 diff --git a/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json new file mode 100644 index 00000000000..5ccbfdd8c03 --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json @@ -0,0 +1,285 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "phc-gnn", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "channels": [ + "anaconda", + "pytorch", + "conda-forge", + "defaults" + ] + }, + "dependencies": [ + { + "purl": "pkg:conda/anaconda/python-dateutil@2.8.1", + "extracted_requirement": "=2.8.1", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/cudatoolkit@10.1", + "extracted_requirement": "=10.1", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/magma-cuda101", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/cudnn@7.6.5", + "extracted_requirement": "=7.6.5", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/pytorch@1.7.1", + "extracted_requirement": "=1.7.1", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/torchvision@0.8.2", + "extracted_requirement": "=0.8.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/torchaudio@0.7.2", + "extracted_requirement": "=0.7.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/numpy@1.19.2", + "extracted_requirement": "=1.19.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/scipy@1.5.2", + "extracted_requirement": "=1.5.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/matplotlib@3.3.2", + "extracted_requirement": "=3.3.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/networkx@2.5", + "extracted_requirement": "=2.5", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/scikit-learn@0.23.2", + "extracted_requirement": "=0.23.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/notebook@6.1.4", + "extracted_requirement": "=6.1.4", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/jupyter_client@6.1.7", + "extracted_requirement": "=6.1.7", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/jupyter_core@4.6.3", + "extracted_requirement": "=4.6.3", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/anaconda/h5py@2.10.0", + "extracted_requirement": "=2.10.0", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/tqdm@4.50.0", + "extracted_requirement": "=4.50.0", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/tensorboard@2.4.0", + "extracted_requirement": "=2.4.0", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ogb@1.2.4", + "extracted_requirement": "==1.2.4", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest@6.2.1", + "extracted_requirement": "==6.2.1", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/bottleneck@1.3.2", + "extracted_requirement": "==1.3.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_yaml", + "purl": "pkg:conda/phc-gnn" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml new file mode 100644 index 00000000000..aacd67479ee --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml @@ -0,0 +1,27 @@ +# https://raw.githubusercontent.com/Genentech/ringer/refs/heads/main/environment.yaml +name: ringer +channels: + - pytorch + - conda-forge + - huggingface +dependencies: + - python=3.8 + - pip + - pytorch::pytorch=1.12 + - huggingface::transformers=4.11.3 + - conda-forge::pytorch-lightning=1.6.4 + - conda-forge::numpy + - conda-forge::scipy + - conda-forge::pandas + - conda-forge::matplotlib + - conda-forge::seaborn + - conda-forge::astropy + - conda-forge::rdkit>=2022.09.5 + - conda-forge::pre-commit + - conda-forge::pytest + - conda-forge::rich + - conda-forge::shellingham + - conda-forge::typer + - conda-forge::wandb + - pip: + - ray diff --git a/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json new file mode 100644 index 00000000000..bcba7bb05c6 --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json @@ -0,0 +1,240 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "ringer", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "channels": [ + "pytorch", + "conda-forge", + "huggingface" + ] + }, + "dependencies": [ + { + "purl": "pkg:conda/pytorch/pytorch@1.12", + "extracted_requirement": "=1.12", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/huggingface/transformers@4.11.3", + "extracted_requirement": "=4.11.3", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytorch-lightning@1.6.4", + "extracted_requirement": "=1.6.4", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numpy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scipy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pandas", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/matplotlib", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/seaborn", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/astropy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/rdkit", + "extracted_requirement": ">=2022.09.5", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pre-commit", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/rich", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/shellingham", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/typer", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/wandb", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ray", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_yaml", + "purl": "pkg:conda/ringer" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/conda/meta.yaml b/tests/packagedcode/data/conda/meta-yaml/abeona/meta.yaml similarity index 100% rename from tests/packagedcode/data/conda/meta.yaml rename to tests/packagedcode/data/conda/meta-yaml/abeona/meta.yaml diff --git a/tests/packagedcode/data/conda/meta.yaml.expected.json b/tests/packagedcode/data/conda/meta-yaml/abeona/meta.yaml-expected.json similarity index 80% rename from tests/packagedcode/data/conda/meta.yaml.expected.json rename to tests/packagedcode/data/conda/meta-yaml/abeona/meta.yaml-expected.json index 3a85a0e3f40..8604df717b8 100644 --- a/tests/packagedcode/data/conda/meta.yaml.expected.json +++ b/tests/packagedcode/data/conda/meta-yaml/abeona/meta.yaml-expected.json @@ -58,32 +58,18 @@ "file_references": [], "is_private": false, "is_virtual": false, - "extra_data": {}, + "extra_data": { + "host": [ + "pip", + "python" + ], + "run": [ + "python >=3.6" + ] + }, "dependencies": [ { - "purl": "pkg:conda/pip", - "extracted_requirement": "", - "scope": "host", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {} - }, - { - "purl": "pkg:conda/python", - "extracted_requirement": "", - "scope": "host", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {} - }, - { - "purl": "pkg:conda/mccortex", + "purl": "pkg:conda/mccortex@1.0", "extracted_requirement": "==1.0", "scope": "run", "is_runtime": true, @@ -94,7 +80,7 @@ "extra_data": {} }, { - "purl": "pkg:conda/nextflow", + "purl": "pkg:conda/nextflow@19.01.0", "extracted_requirement": "==19.01.0", "scope": "run", "is_runtime": true, @@ -105,7 +91,7 @@ "extra_data": {} }, { - "purl": "pkg:conda/cortexpy", + "purl": "pkg:conda/cortexpy@0.45.7", "extracted_requirement": "==0.45.7", "scope": "run", "is_runtime": true, @@ -116,7 +102,7 @@ "extra_data": {} }, { - "purl": "pkg:conda/kallisto", + "purl": "pkg:conda/kallisto@0.44.0", "extracted_requirement": "==0.44.0", "scope": "run", "is_runtime": true, @@ -158,17 +144,6 @@ "is_direct": true, "resolved_package": {}, "extra_data": {} - }, - { - "purl": "pkg:conda/python", - "extracted_requirement": ">=3.6", - "scope": "run", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {} } ], "repository_homepage_url": null, diff --git a/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml b/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml new file mode 100644 index 00000000000..a0f60e8c744 --- /dev/null +++ b/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml @@ -0,0 +1,68 @@ +# https://raw.githubusercontent.com/bioconda/bioconda-recipes/refs/heads/master/recipes/gcnvkernel/meta.yaml + +{% set name = "gcnvkernel" %} +{% set version = "0.9" %} +{% set gatk_version = "4.6.1.0" %} +{% set gatk_sha256 = "ac7015c3f0ef1852745ca0ef647adbf8ddef5db63ab485b00bc1ffe654814155" %} + +package: + name: {{ name|lower }} + version: {{ version }} + +source: + url: https://github.com/broadinstitute/gatk/releases/download/{{ gatk_version }}/gatk-{{ gatk_version }}.zip + sha256: {{ gatk_sha256 }} + +build: + noarch: python + number: 0 + preserve_egg_dir: true + run_exports: + - {{ pin_subpackage('gcnvkernel', max_pin="x") }} + +requirements: + build: + - conda-forge::python =3.10.13 + - unzip + run: + # The following are taken from the GATK python environment: + # + # https://github.com/broadinstitute/gatk/blob/master/scripts/gatkcondaenv.yml.template + - conda-forge::python =3.10.13 + - conda-forge::pip =23.3.1 + - conda-forge:blas =1.0=mkl + - conda-forge::numpy =1.26.2 + - conda-forge::pymc =5.10.1 + - conda-forge::pytensor =2.18.3 + - conda-forge::scipy =1.11.4 + - conda-forge::h5py =3.10.0 + - conda-forge::pytorch =2.1.0=*mkl*100 + - conda-forge::pytorch-lightning =2.4.0 + - conda-forge::scikit-learn =1.3.2 + - conda-forge::matplotlib =3.8.2 + - conda-forge::pandas =2.1.3 + - conda-forge::tqdm =4.66.1 + - conda-forge::dill =0.3.7 + - conda-forge::biopython =1.84 + - r-base =4.3.1 + - r-data.table =1.14.8 + - r-dplyr =1.1.3 + - r-getopt =1.20.4 + - r-ggplot2 =3.4.4 + - r-gplots =3.1.3 + - r-gsalib =2.2.1 + - r-optparse =1.7.3 + - r-backports =1.4.1 + - bioconda::pysam =0.22.0 + - conda-forge::pyvcf =0.6.8 + +test: + imports: + - gcnvkernel + +about: + home: https://www.broadinstitute.org/gatk/ + license: BSD-3-Clause + license_family: BSD + summary: Python package to support GATK gCNV calling. + dev_url: https://github.com/broadinstitute/gatk diff --git a/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml-expected.json b/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml-expected.json new file mode 100644 index 00000000000..e5b7b4a76e0 --- /dev/null +++ b/tests/packagedcode/data/conda/meta-yaml/gcnvkernel/meta.yaml-expected.json @@ -0,0 +1,364 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "gcnvkernel", + "version": "0.9", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": "Python package to support GATK gCNV calling.", + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://www.broadinstitute.org/gatk/", + "download_url": "https://github.com/broadinstitute/gatk/releases/download/4.6.1.0/gatk-4.6.1.0.zip", + "size": null, + "sha1": null, + "md5": null, + "sha256": "ac7015c3f0ef1852745ca0ef647adbf8ddef5db63ab485b00bc1ffe654814155", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": "https://github.com/broadinstitute/gatk", + "copyright": null, + "holder": null, + "declared_license_expression": "bsd-new", + "declared_license_expression_spdx": "BSD-3-Clause", + "license_detections": [ + { + "license_expression": "bsd-new", + "license_expression_spdx": "BSD-3-Clause", + "matches": [ + { + "license_expression": "bsd-new", + "license_expression_spdx": "BSD-3-Clause", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "bsd-new_10.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/bsd-new_10.RULE", + "matched_text": "BSD-3-Clause" + } + ], + "identifier": "bsd_new-50fa5753-f24d-ec04-33a1-36bb8ac0492c" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "BSD-3-Clause", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "build": [ + "conda-forge::python =3.10.13" + ], + "run": [ + "conda-forge::python =3.10.13", + "conda-forge::pip =23.3.1" + ] + }, + "dependencies": [ + { + "purl": "pkg:conda/unzip", + "extracted_requirement": "", + "scope": "build", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge:blas", + "extracted_requirement": "=1.0=mkl", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/numpy", + "extracted_requirement": "=1.26.2", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pymc", + "extracted_requirement": "=5.10.1", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytensor", + "extracted_requirement": "=2.18.3", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/scipy", + "extracted_requirement": "=1.11.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/h5py", + "extracted_requirement": "=3.10.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytorch", + "extracted_requirement": "=2.1.0=*mkl*100", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytorch-lightning", + "extracted_requirement": "=2.4.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/scikit-learn", + "extracted_requirement": "=1.3.2", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/matplotlib", + "extracted_requirement": "=3.8.2", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pandas", + "extracted_requirement": "=2.1.3", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/tqdm", + "extracted_requirement": "=4.66.1", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/dill", + "extracted_requirement": "=0.3.7", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/biopython", + "extracted_requirement": "=1.84", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-base", + "extracted_requirement": "=4.3.1", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-data.table", + "extracted_requirement": "=1.14.8", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-dplyr", + "extracted_requirement": "=1.1.3", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-getopt", + "extracted_requirement": "=1.20.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-ggplot2", + "extracted_requirement": "=3.4.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-gplots", + "extracted_requirement": "=3.1.3", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-gsalib", + "extracted_requirement": "=2.2.1", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-optparse", + "extracted_requirement": "=1.7.3", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/r-backports", + "extracted_requirement": "=1.4.1", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/bioconda/pysam", + "extracted_requirement": "=0.22.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pyvcf", + "extracted_requirement": "=0.6.8", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_yaml", + "purl": "pkg:conda/gcnvkernel@0.9" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml new file mode 100644 index 00000000000..26365ce04af --- /dev/null +++ b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml @@ -0,0 +1,26 @@ +# cmd: conda build . -c auto-mech -c conda-forge +package: + name: pippy + version: "0.1.0" + +source: + path: . + +requirements: + host: + - conda-forge::python=3.7 + run: + - auto-mech::autoio-base + # - conda-forge::python=3.9 + # - conda-forge::numpy=1.21.2 + # - conda-forge::scipy=1.7.1 + - conda-forge::python=3.7 + - conda-forge::numpy=1.15.4 + - conda-forge::scipy=1.5.0 + - conda-forge::pyyaml + - conda-forge::mako + - conda-forge::pytest + - conda-forge::pytest-cov + - conda-forge::future + - conda-forge::flake8 + - conda-forge::pylint diff --git a/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-expected.json b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-expected.json new file mode 100644 index 00000000000..ab6c9d53518 --- /dev/null +++ b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-expected.json @@ -0,0 +1,164 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "pippy", + "version": "0.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "host": [ + "conda-forge::python=3.7" + ], + "run": [ + "conda-forge::python=3.7" + ] + }, + "dependencies": [ + { + "purl": "pkg:conda/auto-mech/autoio-base", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/numpy@1.15.4", + "extracted_requirement": "=1.15.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/scipy@1.5.0", + "extracted_requirement": "=1.5.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pyyaml", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/mako", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytest", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytest-cov", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/future", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/flake8", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pylint", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_yaml", + "purl": "pkg:conda/pippy@0.1.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json new file mode 100644 index 00000000000..d41b17c4418 --- /dev/null +++ b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json @@ -0,0 +1,383 @@ +{ + "packages": [ + { + "type": "conda", + "namespace": null, + "name": "pippy", + "version": "0.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "host": [ + "conda-forge::python=3.7" + ], + "run": [ + "conda-forge::python=3.7" + ] + }, + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "meta.yaml" + ], + "datasource_ids": [ + "conda_meta_yaml" + ], + "purl": "pkg:conda/pippy@0.1.0" + } + ], + "dependencies": [ + { + "purl": "pkg:conda/auto-mech/autoio-base", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/auto-mech/autoio-base?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/numpy@1.15.4", + "extracted_requirement": "=1.15.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/numpy@1.15.4?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/scipy@1.5.0", + "extracted_requirement": "=1.5.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/scipy@1.5.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/pyyaml", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/pyyaml?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/mako", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/mako?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/pytest", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/pytest?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/pytest-cov", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/pytest-cov?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/future", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/future?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/flake8", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/flake8?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/conda-forge/pylint", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/conda-forge/pylint?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "meta.yaml", + "datasource_id": "conda_meta_yaml" + } + ], + "files": [ + { + "path": "meta.yaml", + "type": "file", + "package_data": [ + { + "type": "conda", + "namespace": null, + "name": "pippy", + "version": "0.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "host": [ + "conda-forge::python=3.7" + ], + "run": [ + "conda-forge::python=3.7" + ] + }, + "dependencies": [ + { + "purl": "pkg:conda/auto-mech/autoio-base", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/numpy@1.15.4", + "extracted_requirement": "=1.15.4", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/scipy@1.5.0", + "extracted_requirement": "=1.5.0", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pyyaml", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/mako", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytest", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pytest-cov", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/future", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/flake8", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/conda-forge/pylint", + "extracted_requirement": "", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_yaml", + "purl": "pkg:conda/pippy@0.1.0" + } + ], + "for_packages": [], + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/packagedcode/data/misc/conda/scenicplus.yaml b/tests/packagedcode/data/misc/conda/scenicplus.yaml new file mode 100644 index 00000000000..6c4e874946d --- /dev/null +++ b/tests/packagedcode/data/misc/conda/scenicplus.yaml @@ -0,0 +1,101 @@ +# https://raw.githubusercontent.com/KellisLab/benj/refs/heads/main/conda/scenicplus.yml + +name: scenicplus + +channels: + - conda-forge + - bioconda + +dependencies: + - conda-forge::python==3.8 + - conda-forge::pandas>=1.3.5 + - conda-forge::numpy + - conda-forge::tqdm + - conda-forge::ray-core + - conda-forge::attr + - conda-forge::typing + - conda-forge::matplotlib + - conda-forge::scikit-learn>=0.22.2 + # - conda-forge::statistics + - bioconda::pyranges + - conda-forge::scipy + - bioconda::pybiomart + - conda-forge::requests + - bioconda::arboreto>=0.1.6 + - bioconda::gseapy==0.10.8 + - conda-forge::networkx + - conda-forge::seaborn + - bioconda::pyBigWig + - conda-forge::plotly + - conda-forge::adjustText + - bioconda::macs2 + - conda-forge::lxml + - bioconda::tspex + - conda-forge::kaleido-core + - conda-forge::pyvis + - conda-forge::pygam + - conda-forge::scanpy~=1.9 + - conda-forge::cython + - conda-forge::plotnine + - conda-forge::mudata + - conda-forge::sphinx_rtd_theme + - conda-forge::nbsphinx + - conda-forge::nbsphinx-link + - conda-forge::numpydoc + - conda-forge::sphinx-book-theme + - conda-forge::pip + ### pycisTopic: + - conda-forge::python-annoy + - bioconda::bbknn + - conda-forge::ipython + - conda-forge::ipykernel + - conda-forge::gensim + - bioconda::harmonypy + - conda-forge::ipympl + - conda-forge::leidenalg + - conda-forge::pbr ## req for lda, which conda-forge doesn't have correctly + # - conda-forge::lda + # - conda-forge::loompy==3.0.7 ### conda-forge has not updated recently + - conda-forge::pyopenssl + - conda-forge::polars>=0.11.0 + - bioconda::pybedtools + - bioconda::pyfasta + - conda-forge::python-levenshtein + - bioconda::scanorama + - bioconda::scrublet + - conda-forge::statsmodels + - conda-forge::pytables + - conda-forge::umap-learn + - conda-forge::xlrd + - conda-forge::papermill + - conda-forge::bs4 + - conda-forge::pyarrow + ### pyscenic + - conda-forge::cytoolz + - conda-forge::aiohttp + - conda-forge::llvmlite + - conda-forge::numba>=0.51.2 + - conda-forge::attrs + - conda-forge::frozendict + - conda-forge::numexpr + - conda-forge::cloudpickle + - conda-forge::dask + - conda-forge::distributed + - conda-forge::boltons + - conda-forge::pyyaml + - conda-forge::interlap + - conda-forge::fsspec + ## other + - conda-forge::ply + - conda-forge::pandoc + - conda-forge::globre + - conda-forge::numpy_groupies + - pip: + - git+https://github.com/aertslab/pycisTopic@master#egg=pycisTopic + - git+https://github.com/aertslab/pycistarget@master#egg=pycistarget + - git+https://github.com/aertslab/pySCENIC@master#egg=pyscenic + - git+https://github.com/aertslab/LoomXpy@main#egg=loomxpy + - ctxcore>=0.2.0 + - tmtoolkit + - multiprocessing_on_dill + - lda diff --git a/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json b/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json new file mode 100644 index 00000000000..499a73bf6a0 --- /dev/null +++ b/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json @@ -0,0 +1,921 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "scenicplus", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "channels": [ + "conda-forge", + "bioconda" + ] + }, + "dependencies": [ + { + "purl": "pkg:pypi/pandas", + "extracted_requirement": ">=1.3.5", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numpy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/tqdm", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ray-core", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/attr", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/typing", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/matplotlib", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scikit-learn", + "extracted_requirement": ">=0.22.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyranges", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scipy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pybiomart", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/requests", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/arboreto", + "extracted_requirement": ">=0.1.6", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/gseapy@0.10.8", + "extracted_requirement": "==0.10.8", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/networkx", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/seaborn", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pybigwig", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/plotly", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/adjusttext", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/macs2", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/lxml", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/tspex", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/kaleido-core", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyvis", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pygam", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scanpy", + "extracted_requirement": "~=1.9", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/cython", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/plotnine", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/mudata", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-rtd-theme", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/nbsphinx", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/nbsphinx-link", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numpydoc", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-book-theme", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/python-annoy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/bbknn", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ipython", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ipykernel", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/gensim", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/harmonypy", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ipympl", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/leidenalg", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pbr", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyopenssl", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/polars", + "extracted_requirement": ">=0.11.0", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pybedtools", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyfasta", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/python-levenshtein", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scanorama", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/scrublet", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/statsmodels", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytables", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/umap-learn", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/xlrd", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/papermill", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/bs4", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyarrow", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/cytoolz", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/aiohttp", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/llvmlite", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numba", + "extracted_requirement": ">=0.51.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/attrs", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/frozendict", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numexpr", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/cloudpickle", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/dask", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/distributed", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/boltons", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyyaml", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/interlap", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/fsspec", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ply", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pandoc", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/globre", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/numpy-groupies", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ctxcore", + "extracted_requirement": ">=0.2.0", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/tmtoolkit", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/multiprocessing-on-dill", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/lda", + "extracted_requirement": "", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_yaml", + "purl": "pkg:conda/scenicplus" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/plugin/conda-package-expected.json b/tests/packagedcode/data/plugin/conda-package-expected.json index 3958d5888d0..b0455b31e99 100644 --- a/tests/packagedcode/data/plugin/conda-package-expected.json +++ b/tests/packagedcode/data/plugin/conda-package-expected.json @@ -58,7 +58,14 @@ "source_packages": [], "is_private": false, "is_virtual": false, - "extra_data": {}, + "extra_data": { + "build": [ + "python 3.5.3 1" + ], + "run": [ + "python" + ] + }, "repository_homepage_url": null, "repository_download_url": null, "api_data_url": null, @@ -77,8 +84,8 @@ "purl": "pkg:conda/zlib", "extracted_requirement": "1.2.8 3", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -92,8 +99,8 @@ "purl": "pkg:conda/setuptools", "extracted_requirement": "27.2.0 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -107,8 +114,8 @@ "purl": "pkg:conda/sqlite", "extracted_requirement": "3.13.0 0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -122,8 +129,8 @@ "purl": "pkg:conda/openssl", "extracted_requirement": "1.0.2k 1", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -137,8 +144,8 @@ "purl": "pkg:conda/xz", "extracted_requirement": "5.2.2 1", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -152,8 +159,8 @@ "purl": "pkg:conda/krb5", "extracted_requirement": "1.13.2 0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -167,8 +174,8 @@ "purl": "pkg:conda/pykerberos", "extracted_requirement": "1.1.10 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -178,27 +185,12 @@ "datafile_path": "info/recipe.tar-extract/recipe/meta.yaml", "datasource_id": "conda_meta_yaml" }, - { - "purl": "pkg:conda/python", - "extracted_requirement": "3.5.3 1", - "scope": "build", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {}, - "dependency_uid": "pkg:conda/python?uuid=fixed-uid-done-for-testing-5642512d1758", - "for_package_uid": "pkg:conda/requests-kerberos@0.8.0?uuid=fixed-uid-done-for-testing-5642512d1758", - "datafile_path": "info/recipe.tar-extract/recipe/meta.yaml", - "datasource_id": "conda_meta_yaml" - }, { "purl": "pkg:conda/requests", "extracted_requirement": "2.13.0 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -208,21 +200,6 @@ "datafile_path": "info/recipe.tar-extract/recipe/meta.yaml", "datasource_id": "conda_meta_yaml" }, - { - "purl": "pkg:conda/python", - "extracted_requirement": "", - "scope": "run", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {}, - "dependency_uid": "pkg:conda/python?uuid=fixed-uid-done-for-testing-5642512d1758", - "for_package_uid": "pkg:conda/requests-kerberos@0.8.0?uuid=fixed-uid-done-for-testing-5642512d1758", - "datafile_path": "info/recipe.tar-extract/recipe/meta.yaml", - "datasource_id": "conda_meta_yaml" - }, { "purl": "pkg:conda/requests", "extracted_requirement": ">=1.1.0", @@ -345,14 +322,21 @@ "file_references": [], "is_private": false, "is_virtual": false, - "extra_data": {}, + "extra_data": { + "build": [ + "python 3.5.3 1" + ], + "run": [ + "python" + ] + }, "dependencies": [ { "purl": "pkg:conda/zlib", "extracted_requirement": "1.2.8 3", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -362,8 +346,8 @@ "purl": "pkg:conda/setuptools", "extracted_requirement": "27.2.0 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -373,8 +357,8 @@ "purl": "pkg:conda/sqlite", "extracted_requirement": "3.13.0 0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -384,8 +368,8 @@ "purl": "pkg:conda/openssl", "extracted_requirement": "1.0.2k 1", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -395,8 +379,8 @@ "purl": "pkg:conda/xz", "extracted_requirement": "5.2.2 1", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -406,8 +390,8 @@ "purl": "pkg:conda/krb5", "extracted_requirement": "1.13.2 0", "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -417,19 +401,8 @@ "purl": "pkg:conda/pykerberos", "extracted_requirement": "1.1.10 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {} - }, - { - "purl": "pkg:conda/python", - "extracted_requirement": "3.5.3 1", - "scope": "build", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, @@ -439,19 +412,8 @@ "purl": "pkg:conda/requests", "extracted_requirement": "2.13.0 py35_0", "scope": "build", - "is_runtime": true, - "is_optional": false, - "is_pinned": false, - "is_direct": true, - "resolved_package": {}, - "extra_data": {} - }, - { - "purl": "pkg:conda/python", - "extracted_requirement": "", - "scope": "run", - "is_runtime": true, - "is_optional": false, + "is_runtime": false, + "is_optional": true, "is_pinned": false, "is_direct": true, "resolved_package": {}, diff --git a/tests/packagedcode/data/plugin/plugins_list_linux.txt b/tests/packagedcode/data/plugin/plugins_list_linux.txt index 9468fab2cc4..33886e87222 100755 --- a/tests/packagedcode/data/plugin/plugins_list_linux.txt +++ b/tests/packagedcode/data/plugin/plugins_list_linux.txt @@ -202,6 +202,13 @@ Package type: conda description: Conda meta.yml manifest path_patterns: '*/meta.yaml' -------------------------------------------- +Package type: conda + datasource_id: conda_yaml + documentation URL: https://docs.conda.io/ + primary language: Python + description: Conda yaml manifest + path_patterns: '*conda*.yaml', '*env*.yaml', '*environment*.yaml' +-------------------------------------------- Package type: cpan datasource_id: cpan_dist_ini documentation URL: https://metacpan.org/pod/Dist::Zilla::Tutorial @@ -685,13 +692,6 @@ Package type: pubspec description: Dart pubspec manifest path_patterns: '*pubspec.yaml' -------------------------------------------- -Package type: pypi - datasource_id: conda_yaml - documentation URL: https://docs.conda.io/ - primary language: Python - description: Conda yaml manifest - path_patterns: '*conda.yaml', '*conda.yml' --------------------------------------------- Package type: pypi datasource_id: pip_requirements documentation URL: https://pip.pypa.io/en/latest/reference/requirements-file-format/ diff --git a/tests/packagedcode/test_conda.py b/tests/packagedcode/test_conda.py index 1b50e496796..05df09149a6 100644 --- a/tests/packagedcode/test_conda.py +++ b/tests/packagedcode/test_conda.py @@ -14,14 +14,16 @@ from packages_test_utils import PackageTester from packagedcode import conda from scancode_config import REGEN_TEST_FIXTURES +from scancode.cli_test_utils import run_scan_click +from scancode.cli_test_utils import check_json_scan class TestConda(PackageTester): test_data_dir = os.path.join(os.path.dirname(__file__), 'data') - def test_parse_get_varialble(self): - test_file = self.get_test_loc('conda/meta.yaml') + def test_parse_get_variables(self): + test_file = self.get_test_loc('conda/meta-yaml/abeona/meta.yaml') results = conda.get_variables(test_file) expected = { 'version': '0.45.0', @@ -29,25 +31,85 @@ def test_parse_get_varialble(self): } assert results == expected + def test_parse_get_variables_2(self): + test_file = self.get_test_loc('conda/meta-yaml/gcnvkernel/meta.yaml') + results = conda.get_variables(test_file) + expected = { + 'version': '0.9', + 'name': 'gcnvkernel', + 'gatk_version': '4.6.1.0', + 'gatk_sha256': 'ac7015c3f0ef1852745ca0ef647adbf8ddef5db63ab485b00bc1ffe654814155', + } + assert results == expected + def test_get_meta_yaml_data(self): - test_file = self.get_test_loc('conda/meta.yaml') + test_file = self.get_test_loc('conda/meta-yaml/abeona/meta.yaml') results = conda.get_meta_yaml_data(test_file) assert list(results.items())[0] == (u'package', dict([(u'name', u'abeona'), (u'version', u'0.45.0')])) - def test_condayml_is_package_data_file(self): - test_file = self.get_test_loc('conda/meta.yaml') + def test_conda_meta_yml_is_package_data_file(self): + test_file = self.get_test_loc('conda/meta-yaml/abeona/meta.yaml') assert conda.CondaMetaYamlHandler.is_datafile(test_file) - def test_parse(self): - test_file = self.get_test_loc('conda/meta.yaml') + def test_parse_conda_meta_yaml_with_templates_and_about(self): + test_file = self.get_test_loc('conda/meta-yaml/abeona/meta.yaml') package = conda.CondaMetaYamlHandler.parse(test_file) - expected_loc = self.get_test_loc('conda/meta.yaml.expected.json') + expected_loc = self.get_test_loc('conda/meta-yaml/abeona/meta.yaml-expected.json') self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) - def test_root_dir(self): + def test_conda_meta_yaml_root_dir(self): test_path = 'requests-kerberos-0.8.0-py35_0.tar.bz2-extract/info/recipe.tar-extract/recipe/meta.yaml' test_dir = self.get_test_loc('conda/requests-kerberos-0.8.0-py35_0.tar.bz2-extract') codebase = Codebase(test_dir) resource = codebase.get_resource(path=test_path) proot = conda.CondaMetaYamlHandler.get_conda_root(resource, codebase) assert proot.location == test_dir + + def test_conda_yml_is_package_data_file_with_conda_dir(self): + test_file = self.get_test_loc('misc/conda/scenicplus.yaml') + assert conda.CondaYamlHandler.is_datafile(test_file) + + def test_conda_yml_is_package_data_file_environment(self): + test_file = self.get_test_loc('conda/conda-yaml/phc-gnn/environment_gpu.yml') + assert conda.CondaYamlHandler.is_datafile(test_file) + + def test_parse_conda_meta_yaml_package_from_non_default_channels(self): + test_file = self.get_test_loc('conda/meta-yaml/pippy/meta.yaml') + package = conda.CondaMetaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/meta-yaml/pippy/meta.yaml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_meta_yaml_package_and_assemble(self): + test_file = self.get_test_loc('conda/meta-yaml/pippy/meta.yaml') + result_file = self.get_temp_file('results.json') + run_scan_click(['--package', test_file, '--json', result_file]) + expected_file = self.get_test_loc('conda/meta-yaml/pippy/meta.yaml-scancode.json') + check_json_scan( + expected_file, result_file, remove_uuid=True, regen=REGEN_TEST_FIXTURES + ) + + def test_parse_simple_conda_yaml(self): + test_file = self.get_test_loc('conda/conda-yaml/phc-gnn/environment_gpu.yml') + assert conda.CondaYamlHandler.is_datafile(test_file) + + package = conda.CondaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_yaml_with_pip_source_repos(self): + test_file = self.get_test_loc('misc/conda/scenicplus.yaml') + package = conda.CondaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('misc/conda/scenicplus.yaml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_meta_yaml_with_multiple_templates(self): + test_file = self.get_test_loc('conda/meta-yaml/gcnvkernel/meta.yaml') + package = conda.CondaMetaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/meta-yaml/gcnvkernel/meta.yaml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_yaml_simple_dependencies(self): + test_file = self.get_test_loc('conda/conda-yaml/ringer/environment.yaml') + package = conda.CondaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/conda-yaml/ringer/environment.yaml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) From d610a3957ba7fd2123bfbd37f040b65e2e80303f Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 20:04:17 +0530 Subject: [PATCH 13/29] Bump version to v32.3.1 Signed-off-by: Ayan Sinha Mahapatra --- setup-mini.cfg | 6 +++--- setup.cfg | 4 ++-- src/scancode_config.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/setup-mini.cfg b/setup-mini.cfg index 790faa1187e..b335a995f1d 100644 --- a/setup-mini.cfg +++ b/setup-mini.cfg @@ -1,13 +1,13 @@ [metadata] name = scancode-toolkit-mini -version = 32.3.0 +version = 32.3.1 license = Apache-2.0 AND CC-BY-4.0 AND LicenseRef-scancode-other-permissive AND LicenseRef-scancode-other-copyleft # description must be on ONE line https://github.com/pypa/setuptools/issues/1390 description = ScanCode is a tool to scan code for license, copyright, package and their documented dependencies and other interesting facts. scancode-toolkit-mini is a special build that does not come with pre-built binary dependencies by default. These are instead installed separately or with the extra_requires scancode-toolkit-mini[full] long_description = file:README.rst long_description_content_type = text/x-rst -url = https://github.com/nexB/scancode-toolkit +url = https://github.com/aboutcode-org/scancode-toolkit author = nexB. Inc. and others author_email = info@aboutcode.org @@ -84,7 +84,7 @@ install_requires = javaproperties >= 0.5 jinja2 >= 2.7.0 jsonstreams >= 0.5.0 - license_expression >= 30.1.1 + license_expression >= 30.4.0 lxml >= 4.9.2 MarkupSafe >= 2.1.2 packageurl_python >= 0.9.0 diff --git a/setup.cfg b/setup.cfg index 89f6831818f..31269077d12 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,13 +1,13 @@ [metadata] name = scancode-toolkit -version = 32.3.0 +version = 32.3.1 license = Apache-2.0 AND CC-BY-4.0 AND LicenseRef-scancode-other-permissive AND LicenseRef-scancode-other-copyleft # description must be on ONE line https://github.com/pypa/setuptools/issues/1390 description = ScanCode is a tool to scan code for license, copyright, package and their documented dependencies and other interesting facts. long_description = file:README.rst long_description_content_type = text/x-rst -url = https://github.com/aboutcode-org/skeleton +url = https://github.com/aboutcode-org/scancode-toolkit author = nexB. Inc. and others author_email = info@aboutcode.org diff --git a/src/scancode_config.py b/src/scancode_config.py index fe146456ef2..07560e2db44 100644 --- a/src/scancode_config.py +++ b/src/scancode_config.py @@ -132,12 +132,12 @@ def _create_dir(location): # 4. hardcoded This is the default, fallback version in case package is not installed or we # do not have a proper version otherwise. if not __version__: - __version__ = '32.3.0' + __version__ = '32.3.1' ####################### # used to warn user when the version is out of date # this is (year, month, day) -__release_date__ = datetime.datetime(2024, 10, 21) +__release_date__ = datetime.datetime(2025, 01, 06) # See https://github.com/nexB/scancode-toolkit/issues/2653 for more information # on the data format version From c5e19d2f6d8a578e6fc7120d0292d6cd939c3708 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 20:16:25 +0530 Subject: [PATCH 14/29] Update CHANGELOG for release Signed-off-by: Ayan Sinha Mahapatra --- CHANGELOG.rst | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c80923a1a6e..2a1f48480bb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,8 +14,6 @@ v33.0.0 (next next, roadmap) - Dependencies for - Support for copyright detection objects. -- We can now collect packages from a Rust binary using rust-inspector (Linux-only) - - A new field in packages with the license category for the detected license expression and also an API function to compute license categories from license expressions. @@ -40,6 +38,33 @@ v33.0.0 (next next, roadmap) - Update Dockerfile and test container build. See https://github.com/aboutcode-org/scancode-toolkit/issues/3955 +v32.3.1 - 2024-01-06 +-------------------- + +This is a minor release with license and package detection +improvements, bugfixes and with new and updated license detection rules +and new licenses added. + +- We can now collect packages from a Rust binary using rust-inspector + for rust binaries built with `cargo-auditable`(Linux-only) + Also adds a plugin for colelcting rust symbols with the option + ``--rust-symbol``. See the initial release for more info: + https://github.com/aboutcode-org/rust-inspector/releases/tag/v0.1.0 + https://github.com/aboutcode-org/scancode-toolkit/pull/4043 + +- Improves and adds bugfixes for package detection in the following ecosystems: + conda, npm, rust, go. + https://github.com/aboutcode-org/scancode-toolkit/pull/4073 + +- Updates go-inspector to v0.5.0 . GoReSym is now built from source and has + been updated to v3.0.1. https://github.com/aboutcode-org/scancode-toolkit/pull/3972 + +- Adds new and updated licenses, license detection rules. + https://github.com/aboutcode-org/scancode-toolkit/pull/3963 + +- Adds the latest license-expression with an updated licenseDB. + https://github.com/aboutcode-org/scancode-toolkit/pull/3960 + v32.3.0 - 2024-10-21 -------------------- From 890595ac5bde098660bfef84a0cd138f3a041269 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 20:34:46 +0530 Subject: [PATCH 15/29] Update CI runners Updates the CI runners to use macos-14 instead of macos-12, since this is deprecated. Reference: https://github.com/actions/runner-images/issues/10721 Signed-off-by: Ayan Sinha Mahapatra --- .github/workflows/scancode-release.yml | 4 ++-- azure-pipelines.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/scancode-release.yml b/.github/workflows/scancode-release.yml index 995ff43e38d..f3c18cf0651 100644 --- a/.github/workflows/scancode-release.yml +++ b/.github/workflows/scancode-release.yml @@ -239,7 +239,7 @@ jobs: strategy: fail-fast: true matrix: - os: [ubuntu-22.04, ubuntu-24.04, macos-12, macos-13] + os: [ubuntu-22.04, ubuntu-24.04, macos-13, macos-14] pyver: ["3.9", "3.10", "3.11", "3.12"] steps: @@ -371,7 +371,7 @@ jobs: strategy: fail-fast: true matrix: - os: [macos-12, macos-13] + os: [macos-13, macos-14] pyver: ["3.9", "3.10", "3.11", "3.12"] steps: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cd08e583f74..28389ccc9e7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -138,8 +138,8 @@ jobs: - template: etc/ci/azure-posix.yml parameters: - job_name: macos12_cpython - image_name: macOS-12 + job_name: macos14_cpython + image_name: macOS-14 python_versions: ['3.9', '3.10', '3.11', '3.12'] python_architecture: x64 test_suites: From 5455d8aeb9a87fee0c377638b4a98919ec0fdfc4 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Mon, 6 Jan 2025 20:54:32 +0530 Subject: [PATCH 16/29] Fix release date format Signed-off-by: Ayan Sinha Mahapatra --- src/scancode_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scancode_config.py b/src/scancode_config.py index 07560e2db44..df5b596b4e4 100644 --- a/src/scancode_config.py +++ b/src/scancode_config.py @@ -137,7 +137,7 @@ def _create_dir(location): ####################### # used to warn user when the version is out of date # this is (year, month, day) -__release_date__ = datetime.datetime(2025, 01, 06) +__release_date__ = datetime.datetime(2025, 1, 6) # See https://github.com/nexB/scancode-toolkit/issues/2653 for more information # on the data format version From c9c023e7712044475578d03814f34bb03435d949 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 7 Jan 2025 21:10:31 +0530 Subject: [PATCH 17/29] Fix conda environment yaml parsing errors Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/conda.py | 3 + .../phc-gnn/environment_gpu.yml-expected.json | 2 +- .../ringer/environment.yaml-expected.json | 2 +- .../conda-yaml/test/environment_host_port.yml | 3 + .../environment_host_port.yml-expected.json | 58 +++++++++++++++++++ .../misc/conda/scenicplus.yaml-expected.json | 2 +- tests/packagedcode/test_conda.py | 6 ++ 7 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml create mode 100644 tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml-expected.json diff --git a/src/packagedcode/conda.py b/src/packagedcode/conda.py index 80b71cbb12b..cbe4c1b3534 100644 --- a/src/packagedcode/conda.py +++ b/src/packagedcode/conda.py @@ -51,6 +51,7 @@ def parse(cls, location, package_only=False): primary_language=cls.default_primary_language, dependencies=dependencies, extra_data=extra_data, + is_private=True, ) yield models.PackageData.from_data(package_data, package_only) @@ -205,6 +206,8 @@ def get_conda_yaml_dependencies(conda_data): if "::" in dep: namespace, dep = dep.split("::") + if "/" in namespace or ":" in namespace: + namespace = None req = parse_requirement_line(dep) if req: diff --git a/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json index 5ccbfdd8c03..70b2380e4d2 100644 --- a/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json +++ b/tests/packagedcode/data/conda/conda-yaml/phc-gnn/environment_gpu.yml-expected.json @@ -33,7 +33,7 @@ "notice_text": null, "source_packages": [], "file_references": [], - "is_private": false, + "is_private": true, "is_virtual": false, "extra_data": { "channels": [ diff --git a/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json index bcba7bb05c6..c6f3a8f985b 100644 --- a/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json +++ b/tests/packagedcode/data/conda/conda-yaml/ringer/environment.yaml-expected.json @@ -33,7 +33,7 @@ "notice_text": null, "source_packages": [], "file_references": [], - "is_private": false, + "is_private": true, "is_virtual": false, "extra_data": { "channels": [ diff --git a/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml b/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml new file mode 100644 index 00000000000..bb8a80c496a --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml @@ -0,0 +1,3 @@ +name: test +dependencies: + - https://104.17.92.24:443::flask=1.0.2 diff --git a/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml-expected.json b/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml-expected.json new file mode 100644 index 00000000000..800bfcbab01 --- /dev/null +++ b/tests/packagedcode/data/conda/conda-yaml/test/environment_host_port.yml-expected.json @@ -0,0 +1,58 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "test", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": true, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:conda/flask@1.0.2", + "extracted_requirement": "=1.0.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_yaml", + "purl": "pkg:conda/test" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json b/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json index 499a73bf6a0..ed97094e3f1 100644 --- a/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json +++ b/tests/packagedcode/data/misc/conda/scenicplus.yaml-expected.json @@ -33,7 +33,7 @@ "notice_text": null, "source_packages": [], "file_references": [], - "is_private": false, + "is_private": true, "is_virtual": false, "extra_data": { "channels": [ diff --git a/tests/packagedcode/test_conda.py b/tests/packagedcode/test_conda.py index 05df09149a6..f6998485f10 100644 --- a/tests/packagedcode/test_conda.py +++ b/tests/packagedcode/test_conda.py @@ -113,3 +113,9 @@ def test_parse_conda_yaml_simple_dependencies(self): package = conda.CondaYamlHandler.parse(test_file) expected_loc = self.get_test_loc('conda/conda-yaml/ringer/environment.yaml-expected.json') self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_yaml_does_not_fail_on_test_files_with_port(self): + test_file = self.get_test_loc('conda/conda-yaml/test/environment_host_port.yml') + package = conda.CondaYamlHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/conda-yaml/test/environment_host_port.yml-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) From cb7dbfeb36124e5b2b02232898cfbf50f91af18d Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Wed, 8 Jan 2025 14:47:27 +0530 Subject: [PATCH 18/29] Fix npm workspace parsing bug Reference: https://github.com/aboutcode-org/scancode.io/issues/1521 Reported-by: @JonoYang Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/npm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packagedcode/npm.py b/src/packagedcode/npm.py index 6081f489d17..02dd25153f0 100644 --- a/src/packagedcode/npm.py +++ b/src/packagedcode/npm.py @@ -444,7 +444,8 @@ def get_workspace_members(cls, workspaces, codebase, workspace_root_path): # Case 3: This is a complex glob pattern, we are doing a full codebase walk # and glob matching each resource else: - for resource in workspace_root_path: + workspace_root = codebase.get_resource(path=workspace_root_path) + for resource in workspace_root.walk(codebase): if NpmPackageJsonHandler.is_datafile(resource.location) and fnmatch.fnmatch( name=resource.location, pat=workspace_path, ): From f966c8f313394b919cefbdd8c1c811c9249b5311 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Wed, 8 Jan 2025 19:24:19 +0530 Subject: [PATCH 19/29] Add support for pnpm-lock.yaml v9 See https://github.com/pnpm/spec/blob/master/lockfile/9.0.md Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/npm.py | 63 +- .../v9/uView-pnpm-lock.yaml-expected | 2732 +++++++++++++++++ .../npm/pnpm/pnpm-lock/v9/uView/package.json | 21 + .../pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml | 312 ++ .../teleport/check-redirects-expected.json | 364 +++ .../check-redirects/check-redirects.js | 0 .../teleport/check-redirects/package.json | 18 + .../check-redirects/pnpm-workspace.yaml | 3 + tests/packagedcode/test_npm.py | 15 + 9 files changed, 3521 insertions(+), 7 deletions(-) create mode 100644 tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView-pnpm-lock.yaml-expected create mode 100644 tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/package.json create mode 100644 tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml create mode 100644 tests/packagedcode/data/npm/workspace/teleport/check-redirects-expected.json create mode 100644 tests/packagedcode/data/npm/workspace/teleport/check-redirects/check-redirects.js create mode 100644 tests/packagedcode/data/npm/workspace/teleport/check-redirects/package.json create mode 100644 tests/packagedcode/data/npm/workspace/teleport/check-redirects/pnpm-workspace.yaml diff --git a/src/packagedcode/npm.py b/src/packagedcode/npm.py index 02dd25153f0..779ff281668 100644 --- a/src/packagedcode/npm.py +++ b/src/packagedcode/npm.py @@ -1156,6 +1156,10 @@ def parse(cls, location, package_only=False): yield models.PackageData.from_data(package_data, package_only) +class UnknownPnpmLockFormat(Exception): + pass + + class BasePnpmLockHandler(BaseNpmHandler): @classmethod @@ -1182,7 +1186,28 @@ def parse(cls, location, package_only=False): } major_v, minor_v = lockfile_version.split(".") - resolved_packages = lock_data.get("packages", []) + resolved_packages = lock_data.get("packages", {}) + dependency_relations = lock_data.get("snapshots", {}) + dependency_relations_by_purl = {} + if dependency_relations: + for purl_fields, relations in dependency_relations.items(): + clean_purl_fields = purl_fields.split("(")[0] + sections = clean_purl_fields.split("/") + namespace = None + if len(sections) == 2: + namespace, name_version = sections + elif len(sections) == 1: + name_version, = sections + name, version = name_version.split("@") + + purl = PackageURL( + type=cls.default_package_type, + name=name, + namespace=namespace, + version=version, + ).to_string() + dependency_relations_by_purl[purl] = relations + dependencies_by_purl = {} for purl_fields, data in resolved_packages.items(): @@ -1190,23 +1215,33 @@ def parse(cls, location, package_only=False): clean_purl_fields = purl_fields.split("(")[0] elif major_v == "5" or is_shrinkwrap: clean_purl_fields = purl_fields.split("_")[0] - else: + elif major_v == "9": clean_purl_fields = purl_fields - raise Exception(lockfile_version, purl_fields) + else: + message = f"Unknown pnpm lockfile format: {lockfile_version}" + raise UnknownPnpmLockFormat(message, purl_fields) sections = clean_purl_fields.split("/") - name_version= None + name_version = None + namespace = None if major_v == "6": if len(sections) == 2: - namespace = None _, name_version = sections elif len(sections) == 3: _, namespace, name_version = sections + elif len(sections) == 1: + name_version, = sections + + name, version = name_version.split("@") + elif major_v == "9": + if len(sections) == 2: + namespace, name_version = sections + elif len(sections) == 1: + name_version, = sections name, version = name_version.split("@") elif major_v == "5" or is_shrinkwrap: if len(sections) == 3: - namespace = None _, name, version = sections elif len(sections) == 4: _, namespace, name, version = sections @@ -1224,7 +1259,21 @@ def parse(cls, location, package_only=False): dependencies = data.get('dependencies') or {} optional_dependencies = data.get('optionalDependencies') or {} - transitive_peer_dependencies = data.get('transitivePeerDependencies') or {} + transitive_peer_dependencies = data.get('transitivePeerDependencies') or [] + + if purl in dependency_relations_by_purl: + dependency_relations = dependency_relations_by_purl.get(purl) + if dependency_relations: + deps = dependency_relations.get('dependencies') + if deps: + dependencies.update(deps) + optional_deps = dependency_relations.get('optionalDependencies') + if optional_deps: + optional_dependencies.update(optional_deps) + transitive_peer_deps = dependency_relations.get('transitivePeerDependencies') + if transitive_peer_deps: + transitive_peer_dependencies.extend(transitive_peer_deps) + peer_dependencies = data.get('peerDependencies') or {} peer_dependencies_meta = data.get('peerDependenciesMeta') or {} diff --git a/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView-pnpm-lock.yaml-expected b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView-pnpm-lock.yaml-expected new file mode 100644 index 00000000000..92f17e14479 --- /dev/null +++ b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView-pnpm-lock.yaml-expected @@ -0,0 +1,2732 @@ +[ + { + "type": "npm", + "namespace": null, + "name": null, + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "lockfileVersion": "9.0" + }, + "dependencies": [ + { + "purl": "pkg:npm/%40babel/helper-string-parser@7.24.8", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": "@babel", + "name": "helper-string-parser", + "version": "7.24.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "a4ef4a86145cb94c869c95b0c848274494d22191e24febcc0f490f783faca3497b9b190c4f5f60de98d8f464e71f249c93f843ceaf9db56ff85609cc922a69b1", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/%40babel/helper-string-parser@7.24.8" + }, + "extra_data": { + "engines": { + "node": ">=6.9.0" + } + } + }, + { + "purl": "pkg:npm/%40babel/helper-validator-identifier@7.24.7", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": "@babel", + "name": "helper-validator-identifier", + "version": "7.24.7", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "ad1f8f05c43548c4030f217a5f4c31b46f10c8b0a0501d1e4401a0baa44b7e4080f3b97bc803fb7a1abc48d8fde8e3864cef0e055ef42a1b8561c2241d73a0d3", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/%40babel/helper-validator-identifier@7.24.7" + }, + "extra_data": { + "engines": { + "node": ">=6.9.0" + } + } + }, + { + "purl": "pkg:npm/%40babel/parser@7.25.6", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": "@babel", + "name": "parser", + "version": "7.25.6", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "b6b19d7c175b0f497564f99c27cdde37107dadb11ac7800b15317b7cddfce933186de0906f299ee5c3845d085b19729e6f019a07f279db0d66ae494c71b832e9", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/%40babel/types", + "extracted_requirement": "7.25.6", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/%40babel/parser@7.25.6" + }, + "extra_data": { + "engines": { + "node": ">=6.0.0" + }, + "hasBin": true + } + }, + { + "purl": "pkg:npm/%40babel/types@7.25.6", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": "@babel", + "name": "types", + "version": "7.25.6", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "fe5e36075ab1a46e9175f61fdf8dd4c35be60e378d8677945edce1a2313ba4381fa44ca9991848ea3d64af5ed7095bf80a097d1dd022418db1d06c0a9bbad60b", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/%40babel/helper-string-parser", + "extracted_requirement": "7.24.8", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/%40babel/helper-validator-identifier", + "extracted_requirement": "7.24.7", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/to-fast-properties", + "extracted_requirement": "2.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/%40babel/types@7.25.6" + }, + "extra_data": { + "engines": { + "node": ">=6.9.0" + } + } + }, + { + "purl": "pkg:npm/%40vue/compiler-sfc@2.7.16", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": "@vue", + "name": "compiler-sfc", + "version": "2.7.16", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "296849f64e675ee36dca03d4efeb75ad7e9b6997aa3982c47e8ad43e380d0c19cb89c7c70a88b8f07f3b43c5f22d93ab34db2686ec0aaada434168c415ee8492", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/%40babel/parser", + "extracted_requirement": "7.25.6", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/postcss", + "extracted_requirement": "8.4.47", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/source-map", + "extracted_requirement": "0.6.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/prettier", + "extracted_requirement": "2.8.8", + "scope": "optionalDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/%40vue/compiler-sfc@2.7.16" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/ansi-regex@2.1.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "ansi-regex", + "version": "2.1.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "4c81a74e9768f84dfea42c8096e66fb440f9a79c02a8b75ecc2ca13d9cca3dcc6f169944b788be5bb38e3422a0799153dfecb935965f38e4bf05d71a9e6d4c60", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/ansi-regex@2.1.1" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/anve-upload-upyun@1.0.8", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "anve-upload-upyun", + "version": "1.0.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "f7fdd37ce64ebd21bdd96588bf1232fa4ce30ff2b4eee3adb0c6e03c41f864cabdf23fd16aba0a452e3cc8299fa242dc9d92cbccd9f29583cf71177a8683746f", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/single-line-log", + "extracted_requirement": "1.1.2", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/upyun", + "extracted_requirement": "3.4.6", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/debug", + "extracted_requirement": null, + "scope": "transitivePeerDependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/anve-upload-upyun@1.0.8" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/asynckit@0.4.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "asynckit", + "version": "0.4.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "39e8bd387e2d461d18a94dc6c615fbf5d33f9b0560bdb64969235a464f9bb21923d12e5c7c772061a92b7818eb1f06ad5ca6f3f88a087582f1aca8a6d8c8d6d1", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/asynckit@0.4.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/axios@0.26.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "axios", + "version": "0.26.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "7cfc1c5f812f9d21ee22708c22d1210069da4845d1063b7387d7ceb6c13a1351baa7bbe5ede7447997b5d501dfd7cfbafbd811e4f6ca57fb0628d683f1868c78", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/follow-redirects", + "extracted_requirement": "1.15.9", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/debug", + "extracted_requirement": null, + "scope": "transitivePeerDependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/axios@0.26.1" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/base-64@1.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "base-64", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "9300cf205086c743591e8837e9d8feb478b03f840ccec67702031589404a234f95e67e14d2e7d30943219d0d3876269123c117fd070f7ea97bce5859ee3e3382", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/base-64@1.0.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/charenc@0.0.2", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "charenc", + "version": "0.0.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "cab2d0ff255415793383b10342c3e2784ff9dfed1195a593b3ec01aef5b7e9cca2949d9268359f978623eccb4b4d795e57db8429e7db00650fbf6fe2592a2844", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/charenc@0.0.2" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/code-point-at@1.1.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "code-point-at", + "version": "1.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "4690152900394fadf1123ebf82221b504b59c09e1414873766dbc4922694111ca5a9ef316f922fa9c80ebab64b6a1bfddc22ca7f1730e5823e0d9714051c8b5c", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/code-point-at@1.1.0" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/combined-stream@1.0.8", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "combined-stream", + "version": "1.0.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "1503783117ee25e1dfedc05b04c2455e12920eafb690002b06599106f72f144e410751d9297b5214048385d973f73398c3187c943767be630e7bffb971da0476", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/delayed-stream", + "extracted_requirement": "1.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/combined-stream@1.0.8" + }, + "extra_data": { + "engines": { + "node": ">= 0.8" + } + } + }, + { + "purl": "pkg:npm/crypt@0.0.2", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "crypt", + "version": "0.0.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "982c4196c1c5621f42f8756988469c7a6f051019cc5e053d832e3398d0be497019341ff589d829fdaba5149e058028bb18f1156dfca7834f761aa2f6936ae6a3", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/crypt@0.0.2" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/csstype@3.1.3", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "csstype", + "version": "3.1.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "335b9090c97cad02bfb330f42cd86dab120f2e98a61a6f2c381c14ee52e70a949b4f2637c9e53555cee5e0a4f9cd3e2cff23b11c7e4eeed22eb8b3829cb00347", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/csstype@3.1.3" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/delayed-stream@1.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "delayed-stream", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "672483ecd7fdd5a2c1d11c4be0a1ab28705797b11db350c098475ca156b05e72c3ed20e1a4d82db88236680920edaed04b8d63c4f499d7ba7855d1a730793731", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/delayed-stream@1.0.0" + }, + "extra_data": { + "engines": { + "node": ">=0.4.0" + } + } + }, + { + "purl": "pkg:npm/follow-redirects@1.15.9", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "follow-redirects", + "version": "1.15.9", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "81ec381ac5e2ccd81da11caa9b27cc1f20265ec64393a987912c59142cd6f60c256ed396e38083b586af33ecbeef6a83fd5ab6979e7490c179d834fc7ce2c9a9", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/debug", + "extracted_requirement": "*", + "scope": "peerDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/follow-redirects@1.15.9" + }, + "extra_data": { + "engines": { + "node": ">=4.0" + } + } + }, + { + "purl": "pkg:npm/form-data@4.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "form-data", + "version": "4.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "1131249521a2e6dd10319ba25e803f43abdc9f170b40fe6f76e812a6e0328ba4951a2d9c94f3e9fb180486e31a1c2fb31a09f7d4a776df95b7e5fec7ca491ac3", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/asynckit", + "extracted_requirement": "0.4.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/combined-stream", + "extracted_requirement": "1.0.8", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/mime-types", + "extracted_requirement": "2.1.35", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/form-data@4.0.0" + }, + "extra_data": { + "engines": { + "node": ">= 6" + } + } + }, + { + "purl": "pkg:npm/hmacsha1@1.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "hmacsha1", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "e053fa274a08f23a9bea02cb97db52c15768b1627f00a48627e1f061fe88c5ee0c51c124b2de2e5b3a5542b34e0a29f47f34d141b5d5f1e3e1794f168a20d807", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/hmacsha1@1.0.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/is-buffer@1.1.6", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "is-buffer", + "version": "1.1.6", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "35c7402f0a579139b966fbdb93ba303944af56f04a0e028fe7f7b07d71339e64057ece194666a739e2814e34558e46b7405a0de9727ef45dd44aa7c7a93694e7", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/is-buffer@1.1.6" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/is-fullwidth-code-point@1.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "is-fullwidth-code-point", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "d69a94a918e484f27d9a236af52c0c7ddbe2ea504971de9e171bdf6a2bd085a1f74a08ac7e2bae76f167b5d28e9b1b9e7bfefb97e14f8caad08d6be63e35ab47", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/number-is-nan", + "extracted_requirement": "1.0.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/is-fullwidth-code-point@1.0.0" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/is-promise@4.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "is-promise", + "version": "4.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "86fa6823a928ae124c9de8f6f3975283a9eed7e7babb1b3bcc6dc16009b96f2a83b2024d5b0c7333acfa8998808104784c9df42660533b0a99530dd69721f701", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/is-promise@4.0.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/md5@2.3.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "md5", + "version": "2.3.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "4f51884d898568ab8ef75bf1ca840c1444ecb7e3bbd5550f114df37b918dcc39b439674ff2fd7389368010f52bff790bb18dd27ed833db8d80d527ad4220cbee", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/charenc", + "extracted_requirement": "0.0.2", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/crypt", + "extracted_requirement": "0.0.2", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/is-buffer", + "extracted_requirement": "1.1.6", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/md5@2.3.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/mime-db@1.52.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "mime-db", + "version": "1.52.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "b0f538b95edd625bed589c70c311c3d0fba285536213b4f201b439496c43081f66518bce82ba103b061040e28f27c0886c4fb51135653a82b5502da7537818be", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/mime-db@1.52.0" + }, + "extra_data": { + "engines": { + "node": ">= 0.6" + } + } + }, + { + "purl": "pkg:npm/mime-types@2.1.35", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "mime-types", + "version": "2.1.35", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "64363e6cf9b9cd34c5f98a42ac053d9cad148080983d3d10b53d4d65616fe2cfbe4cd91c815693d20ebee11dae238323423cf2b07075cf1b962f9d21cda7978b", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/mime-db", + "extracted_requirement": "1.52.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/mime-types@2.1.35" + }, + "extra_data": { + "engines": { + "node": ">= 0.6" + } + } + }, + { + "purl": "pkg:npm/nanoid@3.3.7", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "nanoid", + "version": "3.3.7", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "792469a6370f21ab5120c0b553a52780ff1715ccfc31058641db75313050ecd6809af5c37ef3716ef595df1db2e8274451c8824ac0c70d065b858681f10128da", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/nanoid@3.3.7" + }, + "extra_data": { + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + }, + "hasBin": true + } + }, + { + "purl": "pkg:npm/number-is-nan@1.0.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "number-is-nan", + "version": "1.0.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "e236ed657340b1f65b0078a2aa32cf0620a5d7a7444b5cc8e07a73cf1c3ad5393e96817eb010c12b1d4808a28ac08a90eccd26167d539a437b7ae4a771680789", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/number-is-nan@1.0.1" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/picocolors@1.1.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "picocolors", + "version": "1.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "4d0f76981396d25dcb78c7b22d5ea6cf2fe45abf2591dfe1a7799383bc182bbcc986e052b6618c046d0175e0d94bf759c7522e91a5fa064d75cdc967db9a3503", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/picocolors@1.1.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/postcss@8.4.47", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "postcss", + "version": "8.4.47", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "e7aaf10aaec6fd77c1e04917abd1209f9182aae816bc316369f0ce4e121d301b08d798aa3ea479af5e537d2af560f61e108d7d61e6973026d8eaef3c63be862d", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/nanoid", + "extracted_requirement": "3.3.7", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/picocolors", + "extracted_requirement": "1.1.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/source-map-js", + "extracted_requirement": "1.2.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/postcss@8.4.47" + }, + "extra_data": { + "engines": { + "node": "^10 || ^12 || >=14" + } + } + }, + { + "purl": "pkg:npm/prettier@2.8.8", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "prettier", + "version": "2.8.8", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "b5d37ca901af363c380876d8f975e4d098025e7f50885db56b9e6b05ee4b24053e903c82e16427e3e6b09b65df936950324e5f2aea7d5e0cd366d1a48c174ff5", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/prettier@2.8.8" + }, + "extra_data": { + "engines": { + "node": ">=10.13.0" + }, + "hasBin": true + } + }, + { + "purl": "pkg:npm/single-line-log@1.1.2", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "single-line-log", + "version": "1.1.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "6b0cda6883ed60575ec4bafa4c1a5c65218f07a0f54489cd3bfa8d7ad81a265a0f0c5fc3d06915b4bbc6129f089df98b57b0b22f24397c844ffad54dfc999640", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/string-width", + "extracted_requirement": "1.0.2", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/single-line-log@1.1.2" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/source-map-js@1.2.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "source-map-js", + "version": "1.2.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "51758c2a12cec1529bef6f0852d40f5f17d853ebac7726ed52b2bff2e184f0240cbeb84ea70bf30c1c23d108522fb31073bbc8b084811bc550f3e203431a5f40", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/source-map-js@1.2.1" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/source-map@0.6.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "source-map", + "version": "0.6.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "52381aa6e99695b3219018334fb624739617513e3a17488abbc4865ead1b7303f9773fe1d0f963e9e9c9aa3cf565bab697959aa989eb55bc16396332177178ee", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/source-map@0.6.1" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/string-width@1.0.2", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "string-width", + "version": "1.0.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "d17b15a502e75425c725fc84b3cb42d33a53548af93ca2ac42d913dbd230ba99cf4e3b4f990df14ffe32091105f6162457fdccde4cdc513480653e9aea1f35b7", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/code-point-at", + "extracted_requirement": "1.1.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/is-fullwidth-code-point", + "extracted_requirement": "1.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/strip-ansi", + "extracted_requirement": "3.0.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/string-width@1.0.2" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/strip-ansi@3.0.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "strip-ansi", + "version": "3.0.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "561ba64926c1a834cff29d992ca8f8d148c1095e3ebfc6d4484a546f82a34605a4f696ea185e111058fa2846a089d6f67ff33a0330b41261720cd19ac3d382ce", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/ansi-regex", + "extracted_requirement": "2.1.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/strip-ansi@3.0.1" + }, + "extra_data": { + "engines": { + "node": ">=0.10.0" + } + } + }, + { + "purl": "pkg:npm/to-fast-properties@2.0.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "to-fast-properties", + "version": "2.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "fce68a2b4c58aecdc39b1458a8bff20dcf85c455156210e55cc8519afdf3f75e70d87175b67375a26077e788fc55418efe16d1cf20fa637b00eefec64bf71ea2", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/to-fast-properties@2.0.0" + }, + "extra_data": { + "engines": { + "node": ">=4" + } + } + }, + { + "purl": "pkg:npm/upyun@3.4.6", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "upyun", + "version": "3.4.6", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "4e1008ef0a0691513696c3aaf0c1586f439e83c6af39041b6375e65e66aad5a6558f372095c32e23f448981aeaf8a270ee75f7f6234a089298b3ae71880179dd", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/axios", + "extracted_requirement": "0.26.1", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/base-64", + "extracted_requirement": "1.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/form-data", + "extracted_requirement": "4.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/hmacsha1", + "extracted_requirement": "1.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/is-promise", + "extracted_requirement": "4.0.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/md5", + "extracted_requirement": "2.3.0", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/mime-types", + "extracted_requirement": "2.1.35", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/debug", + "extracted_requirement": null, + "scope": "transitivePeerDependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/upyun@3.4.6" + }, + "extra_data": { + "engines": { + "node": ">=8.0.0" + } + } + }, + { + "purl": "pkg:npm/vue-i18n@8.28.2", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "vue-i18n", + "version": "8.28.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "0b91998ecd6d62502a8f0ca669a08f0e30b21a8d746a3529862c00f76da32adf67eca3e9a91ee83353c2c18ce107f13bfa74f7c1f746de846b7b9ada213d6b28", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/vue", + "extracted_requirement": "^2", + "scope": "peerDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/vue-i18n@8.28.2" + }, + "extra_data": {} + }, + { + "purl": "pkg:npm/vue@2.7.16", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_pinned": true, + "is_direct": true, + "resolved_package": { + "type": "npm", + "namespace": null, + "name": "vue", + "version": "2.7.16", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": "e200ad157680037cd865d4e9e6ce07976b28ceec92b20cf88f2d449e904735fa4c6bd74ad59086eef8aa04f0b05ed9a073c9c7a94b00bb71b882d9979246374b", + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:npm/%40vue/compiler-sfc", + "extracted_requirement": "2.7.16", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/csstype", + "extracted_requirement": "3.1.3", + "scope": "dependencies", + "is_runtime": false, + "is_optional": false, + "is_pinned": true, + "is_direct": false, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": "pkg:npm/vue@2.7.16" + }, + "extra_data": { + "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details." + } + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_lock_yaml", + "purl": null + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/package.json b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/package.json new file mode 100644 index 00000000000..f083400f2b1 --- /dev/null +++ b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/package.json @@ -0,0 +1,21 @@ +{ + "name": "uview1.0", + "version": "1.0.0", + "main": "main.js", + "repository": { + "type": "git", + "url": "git+https://github.com/YanxinNet/uView.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/YanxinNet/uView/issues" + }, + "homepage": "https://github.com/YanxinNet/uView#readme", + "dependencies": { + "vue-i18n": "^8.20.0", + "anve-upload-upyun": "^1.0.8" + } + } + \ No newline at end of file diff --git a/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml new file mode 100644 index 00000000000..01fcbbffeda --- /dev/null +++ b/tests/packagedcode/data/npm/pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml @@ -0,0 +1,312 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + anve-upload-upyun: + specifier: ^1.0.8 + version: 1.0.8 + vue-i18n: + specifier: ^8.20.0 + version: 8.28.2(vue@2.7.16) + +packages: + + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.25.6': + resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.25.6': + resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + engines: {node: '>=6.9.0'} + + '@vue/compiler-sfc@2.7.16': + resolution: {integrity: sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + anve-upload-upyun@1.0.8: + resolution: {integrity: sha512-9/3TfOZOvSG92WWIvxIy+kzjD/K07uOtsMbgPEH4ZMq98j/RaroKRS48yCmfokLcnZLLzNnylYPPcRd6hoN0bw==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@0.26.1: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + hmacsha1@1.0.0: + resolution: {integrity: sha512-4FP6J0oI8jqb6gLLl9tSwVdosWJ/AKSGJ+HwYf6Ixe4MUcEkst4uWzpVQrNOCin0fzTRQbXV8ePheU8WiiDYBw==} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + single-line-log@1.1.2: + resolution: {integrity: sha512-awzaaIPtYFdexLr6TBpcZSGPB6D1RInNO/qNetgaJloPDF/D0GkVtLvGEp8InfmLV7CyLyQ5fIRP+tVN/JmWQA==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + upyun@3.4.6: + resolution: {integrity: sha512-ThAI7woGkVE2lsOq8MFYb0Oeg8avOQQbY3XmXmaq1aZVjzcglcMuI/RImBrq+KJw7nX39iNKCJKYs65xiAF53Q==} + engines: {node: '>=8.0.0'} + + vue-i18n@8.28.2: + resolution: {integrity: sha512-C5GZjs1tYlAqjwymaaCPDjCyGo10ajUphiwA922jKt9n7KPpqR7oM1PCwYzhB/E7+nT3wfdG3oRre5raIT1rKA==} + peerDependencies: + vue: ^2 + + vue@2.7.16: + resolution: {integrity: sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==} + deprecated: Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details. + +snapshots: + + '@babel/helper-string-parser@7.24.8': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/parser@7.25.6': + dependencies: + '@babel/types': 7.25.6 + + '@babel/types@7.25.6': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@vue/compiler-sfc@2.7.16': + dependencies: + '@babel/parser': 7.25.6 + postcss: 8.4.47 + source-map: 0.6.1 + optionalDependencies: + prettier: 2.8.8 + + ansi-regex@2.1.1: {} + + anve-upload-upyun@1.0.8: + dependencies: + single-line-log: 1.1.2 + upyun: 3.4.6 + transitivePeerDependencies: + - debug + + asynckit@0.4.0: {} + + axios@0.26.1: + dependencies: + follow-redirects: 1.15.9 + transitivePeerDependencies: + - debug + + base-64@1.0.0: {} + + charenc@0.0.2: {} + + code-point-at@1.1.0: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + crypt@0.0.2: {} + + csstype@3.1.3: {} + + delayed-stream@1.0.0: {} + + follow-redirects@1.15.9: {} + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + hmacsha1@1.0.0: {} + + is-buffer@1.1.6: {} + + is-fullwidth-code-point@1.0.0: + dependencies: + number-is-nan: 1.0.1 + + is-promise@4.0.0: {} + + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + nanoid@3.3.7: {} + + number-is-nan@1.0.1: {} + + picocolors@1.1.0: {} + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + + prettier@2.8.8: + optional: true + + single-line-log@1.1.2: + dependencies: + string-width: 1.0.2 + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + string-width@1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + to-fast-properties@2.0.0: {} + + upyun@3.4.6: + dependencies: + axios: 0.26.1 + base-64: 1.0.0 + form-data: 4.0.0 + hmacsha1: 1.0.0 + is-promise: 4.0.0 + md5: 2.3.0 + mime-types: 2.1.35 + transitivePeerDependencies: + - debug + + vue-i18n@8.28.2(vue@2.7.16): + dependencies: + vue: 2.7.16 + + vue@2.7.16: + dependencies: + '@vue/compiler-sfc': 2.7.16 + csstype: 3.1.3 diff --git a/tests/packagedcode/data/npm/workspace/teleport/check-redirects-expected.json b/tests/packagedcode/data/npm/workspace/teleport/check-redirects-expected.json new file mode 100644 index 00000000000..aeffce08c46 --- /dev/null +++ b/tests/packagedcode/data/npm/workspace/teleport/check-redirects-expected.json @@ -0,0 +1,364 @@ +{ + "packages": [ + { + "type": "npm", + "namespace": null, + "name": "check-redirects", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "packageManager": "pnpm@9.8.0" + }, + "repository_homepage_url": "https://www.npmjs.com/package/check-redirects", + "repository_download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "api_data_url": "https://registry.npmjs.org/check-redirects/1.0.0", + "package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "check-redirects/package.json" + ], + "datasource_ids": [ + "npm_package_json" + ], + "purl": "pkg:npm/check-redirects@1.0.0" + }, + { + "type": "npm", + "namespace": null, + "name": "check-redirects", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "packageManager": "pnpm@9.8.0" + }, + "repository_homepage_url": "https://www.npmjs.com/package/check-redirects", + "repository_download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "api_data_url": "https://registry.npmjs.org/check-redirects/1.0.0", + "package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "check-redirects/package.json" + ], + "datasource_ids": [ + "npm_package_json" + ], + "purl": "pkg:npm/check-redirects@1.0.0" + } + ], + "dependencies": [ + { + "purl": "pkg:npm/yargs", + "extracted_requirement": "^17.7.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/yargs?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + }, + { + "purl": "pkg:npm/jest", + "extracted_requirement": "^29.7.0", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/jest?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + }, + { + "purl": "pkg:npm/memfs", + "extracted_requirement": "^4.11.1", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/memfs?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + }, + { + "purl": "pkg:npm/yargs", + "extracted_requirement": "^17.7.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/yargs?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + }, + { + "purl": "pkg:npm/jest", + "extracted_requirement": "^29.7.0", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/jest?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + }, + { + "purl": "pkg:npm/memfs", + "extracted_requirement": "^4.11.1", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:npm/memfs?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "check-redirects/package.json", + "datasource_id": "npm_package_json" + } + ], + "files": [ + { + "path": "check-redirects", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "check-redirects/check-redirects.js", + "type": "file", + "package_data": [], + "for_packages": [ + "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "check-redirects/package.json", + "type": "file", + "package_data": [ + { + "type": "npm", + "namespace": null, + "name": "check-redirects", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "packageManager": "pnpm@9.8.0" + }, + "dependencies": [ + { + "purl": "pkg:npm/yargs", + "extracted_requirement": "^17.7.2", + "scope": "dependencies", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/jest", + "extracted_requirement": "^29.7.0", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:npm/memfs", + "extracted_requirement": "^4.11.1", + "scope": "devDependencies", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://www.npmjs.com/package/check-redirects", + "repository_download_url": "https://registry.npmjs.org/check-redirects/-/check-redirects-1.0.0.tgz", + "api_data_url": "https://registry.npmjs.org/check-redirects/1.0.0", + "datasource_id": "npm_package_json", + "purl": "pkg:npm/check-redirects@1.0.0" + } + ], + "for_packages": [ + "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "check-redirects/pnpm-workspace.yaml", + "type": "file", + "package_data": [ + { + "type": "npm", + "namespace": null, + "name": null, + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "JavaScript", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "workspaces": [ + "**" + ] + }, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pnpm_workspace_yaml", + "purl": null + } + ], + "for_packages": [ + "pkg:npm/check-redirects@1.0.0?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/packagedcode/data/npm/workspace/teleport/check-redirects/check-redirects.js b/tests/packagedcode/data/npm/workspace/teleport/check-redirects/check-redirects.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/packagedcode/data/npm/workspace/teleport/check-redirects/package.json b/tests/packagedcode/data/npm/workspace/teleport/check-redirects/package.json new file mode 100644 index 00000000000..5b2ded3cd28 --- /dev/null +++ b/tests/packagedcode/data/npm/workspace/teleport/check-redirects/package.json @@ -0,0 +1,18 @@ +{ + "name": "check-redirects", + "version": "1.0.0", + "type": "module", + "scripts": { + "check-redirects": "node index.js", + "test": "NODE_OPTIONS=--experimental-vm-modules jest" + }, + "dependencies": { + "yargs": "^17.7.2" + }, + "devDependencies": { + "jest": "^29.7.0", + "memfs": "^4.11.1" + }, + "packageManager": "pnpm@9.8.0" + } + \ No newline at end of file diff --git a/tests/packagedcode/data/npm/workspace/teleport/check-redirects/pnpm-workspace.yaml b/tests/packagedcode/data/npm/workspace/teleport/check-redirects/pnpm-workspace.yaml new file mode 100644 index 00000000000..5ff223a40e7 --- /dev/null +++ b/tests/packagedcode/data/npm/workspace/teleport/check-redirects/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +# https://github.com/pnpm/pnpm/issues/2412 +packages: + - "**" diff --git a/tests/packagedcode/test_npm.py b/tests/packagedcode/test_npm.py index 2e5d5e4f336..ea4b78ed413 100644 --- a/tests/packagedcode/test_npm.py +++ b/tests/packagedcode/test_npm.py @@ -394,6 +394,12 @@ def test_parse_pnpm_lock_yaml_v6(self): packages = npm.PnpmLockYamlHandler.parse(test_file) self.check_packages_data(packages, expected_loc, regen=REGEN_TEST_FIXTURES) + def test_parse_pnpm_lock_yaml_v9(self): + test_file = self.get_test_loc('npm/pnpm/pnpm-lock/v9/uView/pnpm-lock.yaml') + expected_loc = self.get_test_loc('npm/pnpm/pnpm-lock/v9/uView-pnpm-lock.yaml-expected') + packages = npm.PnpmLockYamlHandler.parse(test_file) + self.check_packages_data(packages, expected_loc, regen=REGEN_TEST_FIXTURES) + def test_parse_pnpm_shrinkwrap_yaml(self): test_file = self.get_test_loc('npm/pnpm/shrinkwrap/v3/vuepack/shrinkwrap.yaml') expected_loc = self.get_test_loc('npm/pnpm/shrinkwrap/v3/vuepack-shrinkwrap.yaml-expected') @@ -415,6 +421,15 @@ def test_pnpm_scan_with_workspace_package_json(self): expected_file, result_file, remove_uuid=True, regen=REGEN_TEST_FIXTURES ) + def test_pnpm_scan_with_patterns_in_workspace(self): + test_folder = self.get_test_loc('npm/workspace/teleport/check-redirects/') + expected_file = self.get_test_loc('npm/workspace/teleport/check-redirects-expected.json') + result_file = self.get_temp_file('results.json') + run_scan_click(['--package', test_folder, '--json', result_file]) + check_json_scan( + expected_file, result_file, remove_uuid=True, regen=REGEN_TEST_FIXTURES + ) + def test_pnpm_scan_with_simple_package_json(self): test_folder = self.get_test_loc('npm/pnpm/pnpm-lock/v6/tabler/') expected_file = self.get_test_loc('npm/pnpm/pnpm-lock/v6/tabler-scan.expected.json') From c2aaa1dcf493320d5d3b81491c4827d95b3a8cd4 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Wed, 8 Jan 2025 20:26:39 +0530 Subject: [PATCH 20/29] Add new licenses These license were added to dejacode by @DennisClark Signed-off-by: Ayan Sinha Mahapatra --- .../activepieces-enterprise-2023.LICENSE | 47 ++++++++++ .../data/licenses/cryptoswift.LICENSE | 33 +++++++ .../data/licenses/omg-bpmn-2.0.LICENSE | 91 +++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 src/licensedcode/data/licenses/activepieces-enterprise-2023.LICENSE create mode 100644 src/licensedcode/data/licenses/cryptoswift.LICENSE create mode 100644 src/licensedcode/data/licenses/omg-bpmn-2.0.LICENSE diff --git a/src/licensedcode/data/licenses/activepieces-enterprise-2023.LICENSE b/src/licensedcode/data/licenses/activepieces-enterprise-2023.LICENSE new file mode 100644 index 00000000000..3d0cab107e5 --- /dev/null +++ b/src/licensedcode/data/licenses/activepieces-enterprise-2023.LICENSE @@ -0,0 +1,47 @@ +--- +key: activepieces-enterprise-2023 +short_name: Activepieces Enterprise License 2023 +name: Activepieces Enterprise License 2023 +category: Commercial +owner: Activepieces +homepage_url: https://github.com/activepieces/activepieces/blob/main/packages/ee/LICENSE +spdx_license_key: LicenseRef-scancode-activepieces-enterprise-2023 +ignorable_urls: + - https://activepieces.com/terms +--- + +The Activepieces Enterprise license (the “Enterprise License”) + +With regard to the Activepieces Software: + +This software and associated documentation files (the "Software") may only be +used in production, if you (and any entity that you represent) have agreed to, +and are in compliance with, the Activepieces Subscription Terms of Service, available +at https://activepieces.com/terms (the “Enterprise Terms”), or other +agreement governing the use of the Software, as agreed by you and Activepieces, +and otherwise have a valid Activepieces Enterprise license for the +correct number of user seats. Subject to the foregoing sentence, you are free to +modify this Software and publish patches to the Software. You agree that Activepieces +and/or its licensors (as applicable) retain all right, title and interest in and +to all such modifications and/or patches, and all such modifications and/or +patches may only be used, copied, modified, displayed, distributed, or otherwise +exploited with a valid Activepieces Enterprise license for the correct +number of user seats. Notwithstanding the foregoing, you may copy and modify +the Software for development and testing purposes, without requiring a +subscription. You agree that Activepieces and/or its licensors (as applicable) retain +all right, title and interest in and to all such modifications. You are not +granted any other rights beyond what is expressly stated herein. Subject to the +foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, +and/or sell the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +For all third party components incorporated into the Activepieces Software, those +components are licensed under the original license provided by the owner of the +applicable component. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/cryptoswift.LICENSE b/src/licensedcode/data/licenses/cryptoswift.LICENSE new file mode 100644 index 00000000000..36343b2006b --- /dev/null +++ b/src/licensedcode/data/licenses/cryptoswift.LICENSE @@ -0,0 +1,33 @@ +--- +key: cryptoswift +short_name: CryptoSwift License +name: CryptoSwift License +category: Permissive +owner: Marcin Krzyzanowski +homepage_url: https://github.com/krzyzanowskim/CryptoSwift/blob/main/LICENSE +spdx_license_key: LicenseRef-scancode-cryptoswift +other_urls: + - https://github.com/krzyzanowskim/CryptoSwift/blob/main/CONTRIBUTING.md +ignorable_copyrights: + - Copyright (c) 2014-3099 Marcin Krzyzanowski +ignorable_holders: + - Marcin Krzyzanowski +ignorable_authors: + - the Marcin Krzyzanowski (http://krzyzanowskim.com/) +ignorable_urls: + - http://krzyzanowskim.com/ +ignorable_emails: + - marcin.krzyzanowski@gmail.com +--- + +Copyright (C) 2014-3099 Marcin Krzyżanowski +This software is provided 'as-is', without any express or implied warranty. + +In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. +- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +- This notice may not be removed or altered from any source or binary distribution. +- Redistributions of any form whatsoever must retain the following acknowledgment: 'This product includes software developed by the "Marcin Krzyzanowski" (http://krzyzanowskim.com/).' \ No newline at end of file diff --git a/src/licensedcode/data/licenses/omg-bpmn-2.0.LICENSE b/src/licensedcode/data/licenses/omg-bpmn-2.0.LICENSE new file mode 100644 index 00000000000..98a872c4459 --- /dev/null +++ b/src/licensedcode/data/licenses/omg-bpmn-2.0.LICENSE @@ -0,0 +1,91 @@ +--- +key: omg-bpmn-2.0 +short_name: OMG BPMN 2.0 +name: OMG Business Process Model and Notation 2.0 +category: Proprietary Free +owner: OMG +homepage_url: https://www.omg.org/spec/BPMN/2.0 +spdx_license_key: LicenseRef-scancode-omg-bpmn-2.0 +text_urls: + - https://www.omg.org/spec/BPMN/2.0/PDF +other_urls: + - https://issues.apache.org/jira/browse/LEGAL-690 +--- + +USE OF SPECIFICATION - TERMS, CONDITIONS & NOTICES +The material in this document details an Object Management Group specification in accordance with the terms, +conditions and notices set forth below. This document does not represent a commitment to implement any portion of this +specification in any company's products. The information contained in this document is subject to change without notice. + +LICENSES +The companies listed above have granted to the Object Management Group, Inc. (OMG) a nonexclusive, royalty-free, +paid up, worldwide license to copy and distribute this document and to modify this document and distribute copies of the +modified version. Each of the copyright holders listed above has agreed that no person shall be deemed to have infringed +the copyright in the included material of any such copyright holder by reason of having used the specification set forth +herein or having conformed any computer software to the specification. +Subject to all of the terms and conditions below, the owners of the copyright in this specification hereby grant you a fully- +paid up, non-exclusive, nontransferable, perpetual, worldwide license (without the right to sublicense), to use this +specification to create and distribute software and special purpose specifications that are based upon this specification, +and to use, copy, and distribute this specification as provided under the Copyright Act; provided that: (1) both the +copyright notice identified above and this permission notice appear on any copies of this specification; (2) the use of the +specifications is for informational purposes and will not be copied or posted on any network computer or broadcast in any +media and will not be otherwise resold or transferred for commercial purposes; and (3) no modifications are made to this +specification. This limited permission automatically terminates without notice if you breach any of these terms or +conditions. Upon termination, you will destroy immediately any copies of the specifications in your possession or control. + +PATENTS +The attention of adopters is directed to the possibility that compliance with or adoption of OMG specifications may +require use of an invention covered by patent rights. OMG shall not be responsible for identifying patents for which a +license may be required by any OMG specification, or for conducting legal inquiries into the legal validity or scope of +those patents that are brought to its attention. OMG specifications are prospective and advisory only. Prospective users are +responsible for protecting themselves against liability for infringement of patents. + +GENERAL USE RESTRICTIONS +Any unauthorized use of this specification may violate copyright laws, trademark laws, and communications regulations +and statutes. This document contains information which is protected by copyright. All Rights Reserved. No part of this +work covered by copyright herein may be reproduced or used in any form or by any means--graphic, electronic, or +mechanical, including photocopying, recording, taping, or information storage and retrieval systems--without permission +of the copyright owner. + +DISCLAIMER OF WARRANTY +WHILE THIS PUBLICATION IS BELIEVED TO BE ACCURATE, IT IS PROVIDED "AS IS" AND MAY CONTAIN +ERRORS OR MISPRINTS. THE OBJECT MANAGEMENT GROUP AND THE COMPANIES LISTED ABOVE +MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS PUBLICATION, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF TITLE OR OWNERSHIP, IMPLIED WARRANTY OF +MERCHANTABILITY OR WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE. +IN NO EVENT SHALL THE OBJECT MANAGEMENT GROUP OR ANY OF THE COMPANIES LISTED ABOVE +BE LIABLE FOR ERRORS CONTAINED HEREIN OR FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +CONSEQUENTIAL, RELIANCE OR COVER DAMAGES, INCLUDING LOSS OF PROFITS, REVENUE, DATA OR +USE, INCURRED BY ANY USER OR ANY THIRD PARTY IN CONNECTION WITH THE FURNISHING, +PERFORMANCE, OR USE OF THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. +The entire risk as to the quality and performance of software developed using this specification is borne by you. This +disclaimer of warranty constitutes an essential part of the license granted to you to use this specification. + +RESTRICTED RIGHTS LEGEND +Use, duplication or disclosure by the U.S. Government is subject to the restrictions set forth in subparagraph (c) (1) (ii) of +The Rights in Technical Data and Computer Software Clause at DFARS 252.227-7013 or in subparagraph (c)(1) and (2) +of the Commercial Computer Software - Restricted Rights clauses at 48 C.F.R. 52.227-19 or as specified in 48 C.F.R. 227- +7202-2 of the DoD F.A.R. Supplement and its successors, or as specified in 48 C.F.R. 12.212 of the Federal Acquisition +Regulations and its successors, as applicable. The specification copyright owners are as indicated above and may be +contacted through the Object Management Group, 140 Kendrick Street, Needham, MA 02494, U.S.A. + +TRADEMARKS +MDA®, Model Driven Architecture®, UML®, UML Cube logo®, OMG Logo®, CORBA® and XMI® are registered +trademarks of the Object Management Group, Inc., and Object Management Group™, OMG™ , Unified Modeling +Language™, Model Driven Architecture Logo™, Model Driven Architecture Diagram™, CORBA logos™, XMI +Logo™, CWM™, CWM Logo™, IIOP™ , IMM™ , MOF™ , OMG Interface Definition Language (IDL)™ , and OMG +Systems Modeling Language (OMG SysML)™ are trademarks of the Object Management Group. All other products or +company names mentioned are used for identification purposes only, and may be trademarks of their respective owners. + +COMPLIANCE +The copyright holders listed above acknowledge that the Object Management Group (acting itself or through its +designees) is and shall at all times be the sole entity that may authorize developers, suppliers and sellers of computer +software to use certification marks, trademarks or other special designations to indicate compliance with these materials. +Software developed under the terms of this license may claim compliance or conformance with this specification if and +only if the software compliance is of a nature fully matching the applicable compliance points as stated in the +specification. Software developed only partially matching the applicable compliance points may claim only that the +software was based on this specification, but may not claim compliance or conformance with this specification. In the +event that testing suites are implemented or approved by Object Management Group, Inc., software developed using this +specification may claim compliance or conformance with the specification only if the software satisfactorily completes +the testing suites. \ No newline at end of file From 924718e86cff467c6d64ba8eada4b1aad53fb5c3 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Wed, 8 Jan 2025 21:00:52 +0530 Subject: [PATCH 21/29] Add licenses from SPDX License list 3.26 Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/4045 Signed-off-by: Ayan Sinha Mahapatra --- .../licenses/any-osi-perl-modules.LICENSE | 22 +++++ .../licenses/apache-patent-exception.LICENSE | 7 +- .../data/licenses/cc-pdm-1.0.LICENSE | 7 +- .../data/licenses/cc-sa-1.0.LICENSE | 4 +- .../licenses/cgal-linking-exception.LICENSE | 15 ++++ .../data/licenses/click-license.LICENSE | 4 +- .../data/licenses/docbook-stylesheet.LICENSE | 22 +++++ .../data/licenses/generic-xts.LICENSE | 26 ++++++ .../gpl-3.0-389-ds-base-exception.LICENSE | 18 ++++ .../data/licenses/guile-exception-2.0.LICENSE | 5 +- .../independent-modules-exception.LICENSE | 28 +++++++ .../data/licenses/inno-setup.LICENSE | 4 +- src/licensedcode/data/licenses/mips.LICENSE | 16 ++++ .../licenses/sendmail-open-source-1.1.LICENSE | 84 +++++++++++++++++++ .../data/licenses/smail-gpl.LICENSE | 6 +- .../data/licenses/stlport-4.5.LICENSE | 6 +- .../data/licenses/thirdeye.LICENSE | 16 ++++ .../data/licenses/trustedqsl.LICENSE | 67 +++++++++++++++ src/licensedcode/data/licenses/wwl.LICENSE | 14 ++++ ...with_broadcom-linking-exception-2.0_1.RULE | 6 +- .../data/rules/other-permissive_116.RULE | 4 + .../other-permissive_or_gpl-1.0-plus_2.RULE | 4 + 22 files changed, 375 insertions(+), 10 deletions(-) create mode 100644 src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE create mode 100644 src/licensedcode/data/licenses/cgal-linking-exception.LICENSE create mode 100644 src/licensedcode/data/licenses/docbook-stylesheet.LICENSE create mode 100644 src/licensedcode/data/licenses/generic-xts.LICENSE create mode 100644 src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE create mode 100644 src/licensedcode/data/licenses/independent-modules-exception.LICENSE create mode 100644 src/licensedcode/data/licenses/mips.LICENSE create mode 100644 src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE create mode 100644 src/licensedcode/data/licenses/thirdeye.LICENSE create mode 100644 src/licensedcode/data/licenses/trustedqsl.LICENSE create mode 100644 src/licensedcode/data/licenses/wwl.LICENSE diff --git a/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE b/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE new file mode 100644 index 00000000000..bdccf7234a1 --- /dev/null +++ b/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE @@ -0,0 +1,22 @@ +--- +key: any-osi-perl-modules +short_name: Any OSI Perl Modules +name: Any OSI License - Perl Modules +spdx_license_key: any-OSI-perl-modules +other_urls: + - https://metacpan.org/release/JUERD/Exporter-Tidy-0.09/view/Tidy.pm#LICENSE + - https://metacpan.org/pod/Qmail::Deliverable::Client#LICENSE + - https://metacpan.org/pod/Net::MQTT::Simple#LICENSE +--- + +This software may be redistributed under the terms of the GPL, LGPL, +modified BSD, or Artistic license, or any of the other OSI approved +licenses listed at http://www.opensource.org/licenses/alphabetical. +Distribution is allowed under all of these licenses, or any smaller +subset of multiple or just one of these licenses. + +When using a packaged version, please refer to the package metadata to see +under which license terms it was distributed. Alternatively, a distributor +may choose to replace the LICENSE section of the documentation and/or +include a LICENSE file to reflect the license(s) they chose to redistribute +under. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/apache-patent-exception.LICENSE b/src/licensedcode/data/licenses/apache-patent-exception.LICENSE index d6911eb56b3..f56e60e2051 100644 --- a/src/licensedcode/data/licenses/apache-patent-exception.LICENSE +++ b/src/licensedcode/data/licenses/apache-patent-exception.LICENSE @@ -6,9 +6,12 @@ category: Permissive owner: Michael R Sweet homepage_url: https://github.com/michaelrsweet/mxml/blob/c44aa254ccd90b10b260f04cf9e499bbf971c257/NOTICE is_exception: yes -spdx_license_key: LicenseRef-scancode-apache-patent-exception +spdx_license_key: mxml-exception other_spdx_license_keys: - - LicenseRef-scancode-apache-patent-provision-exception + - LicenseRef-scancode-apache-patent-exception +other_urls: + - https://github.com/michaelrsweet/mxml/blob/master/LICENSE + - https://github.com/michaelrsweet/mxml/blob/master/NOTICE --- (Optional) Exceptions to the Apache 2.0 License: diff --git a/src/licensedcode/data/licenses/cc-pdm-1.0.LICENSE b/src/licensedcode/data/licenses/cc-pdm-1.0.LICENSE index f070362dcbd..35abf71e80c 100644 --- a/src/licensedcode/data/licenses/cc-pdm-1.0.LICENSE +++ b/src/licensedcode/data/licenses/cc-pdm-1.0.LICENSE @@ -5,8 +5,13 @@ name: Creative Commons Public Domain Mark 1.0 category: Public Domain owner: Creative Commons homepage_url: https://creativecommons.org/publicdomain/mark/1.0/ -spdx_license_key: LicenseRef-scancode-cc-pdm-1.0 +spdx_license_key: CC-PDM-1.0 +other_spdx_license_keys: + - LicenseRef-scancode-cc-pdm-1.0 faq_url: https://wiki.creativecommons.org/wiki/PDM_FAQ +other_urls: + - https://creativecommons.org/share-your-work/cclicenses/ + - https://creativecommons.org/publicdomain/mark/1.0/ --- Public Domain Mark 1.0 diff --git a/src/licensedcode/data/licenses/cc-sa-1.0.LICENSE b/src/licensedcode/data/licenses/cc-sa-1.0.LICENSE index 3db3c8cdaf9..38e3d5b4de7 100644 --- a/src/licensedcode/data/licenses/cc-sa-1.0.LICENSE +++ b/src/licensedcode/data/licenses/cc-sa-1.0.LICENSE @@ -11,7 +11,9 @@ notes: A deprecated license from Creative Commons that predates the use of the " CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. -spdx_license_key: LicenseRef-scancode-cc-sa-1.0 +spdx_license_key: CC-SA-1.0 +other_spdx_license_keys: + - LicenseRef-scancode-cc-sa-1.0 text_urls: - http://creativecommons.org/licenses/sa/1.0/legalcode faq_url: https://web.archive.org/web/20140321162027/http://creativecommons.org/licenses/sa/1.0/ diff --git a/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE new file mode 100644 index 00000000000..22bc8f0553b --- /dev/null +++ b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE @@ -0,0 +1,15 @@ +--- +key: cgal-linking-exception +short_name: CGAL Linking Exception +name: CGAL Linking Exception +is_exception: yes +spdx_license_key: CGAL-linking-exception +other_urls: + - https://github.com/openscad/openscad/blob/openscad-2021.01/COPYING#L3 + - https://github.com/floriankirsch/OpenCSG/blob/opencsg-1-4-2-release/license.txt#L3 +--- + +As a special exception, you have permission to link this library +with the CGAL library (http://www.cgal.org) and distribute executables, +as long as you follow the requirements of the GNU GPL in regard to +all of the software in the executable aside from CGAL. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/click-license.LICENSE b/src/licensedcode/data/licenses/click-license.LICENSE index f704c3b6014..92b058125ee 100644 --- a/src/licensedcode/data/licenses/click-license.LICENSE +++ b/src/licensedcode/data/licenses/click-license.LICENSE @@ -5,7 +5,9 @@ name: Click License category: Permissive owner: Unspecified homepage_url: https://changelogs.ubuntu.com/changelogs/pool/main/t/t1utils/t1utils_1.39-2/copyright -spdx_license_key: LicenseRef-scancode-click-license +spdx_license_key: MIT-Click +other_spdx_license_keys: + - LicenseRef-scancode-click-license minimum_coverage: 80 --- diff --git a/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE b/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE new file mode 100644 index 00000000000..35dff87b998 --- /dev/null +++ b/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE @@ -0,0 +1,22 @@ +--- +key: docbook-stylesheet +short_name: DocBook Stylesheet License +name: DocBook Stylesheet License +spdx_license_key: DocBook-Stylesheet +other_urls: + - http://www.docbook.org/xml/5.0/docbook-5.0.zip +--- + +Copyright 2005 Norman Walsh, Sun Microsystems, +Inc., and the Organization for the Advancement +of Structured Information Standards (OASIS). + +Release: $Id: db4-upgrade.xsl 8905 2010-09-12 11:47:07Z bobstayton $ + +Permission to use, copy, modify and distribute this stylesheet +and its accompanying documentation for any purpose and +without fee is hereby granted in perpetuity, provided that +the above copyright notice and this paragraph appear in +all copies. The copyright holders make no representation +about the suitability of the schema for any purpose. It +is provided "as is" without expressed or implied warranty. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/generic-xts.LICENSE b/src/licensedcode/data/licenses/generic-xts.LICENSE new file mode 100644 index 00000000000..146a3eb82eb --- /dev/null +++ b/src/licensedcode/data/licenses/generic-xts.LICENSE @@ -0,0 +1,26 @@ +--- +key: generic-xts +short_name: Generic XTS License +name: Generic XTS License +spdx_license_key: generic-xts +other_urls: + - https://github.com/mhogomchungu/zuluCrypt/blob/master/external_libraries/tcplay/generic_xts.c +--- + +Copyright (C) 2008, Damien Miller +Copyright (C) 2011, Alex Hornung + +Permission to use, copy, and modify this software with or without fee +is hereby granted, provided that this entire notice is included in +all copies of any software which is or includes a copy or +modification of this software. +You may use this code under the GNU public license if you so wish. Please +contribute changes back to the authors under this freer than GPL license +so that we may further the use of strong encryption without limitations to +all. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR +IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY +REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE +MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR +PURPOSE. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE b/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE new file mode 100644 index 00000000000..d7c0bc59a9d --- /dev/null +++ b/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE @@ -0,0 +1,18 @@ +--- +key: gpl-3.0-389-ds-base-exception +short_name: GPL-3.0 389 DS Base Exception +name: GPL-3.0 389 DS Base Exception +is_exception: yes +spdx_license_key: GPL-3.0-389-ds-base-exception +--- + +Additional permission under GPLv3 section 7: + +If you modify this Program, or any covered work, by +linking or combining it with OpenSSL, or a modified +version of OpenSSL licensed under the OpenSSL license +(https://www.openssl.org/source/license.html), the licensors of this +Program grant you additional permission to convey the resulting work. +Corresponding Source for a non-source form of such a combination +shall include the source code for the parts that are licensed +under the OpenSSL license as well as that of the covered work. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/guile-exception-2.0.LICENSE b/src/licensedcode/data/licenses/guile-exception-2.0.LICENSE index 5e87d19981d..896cb7a8047 100644 --- a/src/licensedcode/data/licenses/guile-exception-2.0.LICENSE +++ b/src/licensedcode/data/licenses/guile-exception-2.0.LICENSE @@ -5,9 +5,12 @@ name: GUILE exception to GPL 2.0 category: Copyleft Limited owner: Free Software Foundation (FSF) is_exception: yes -spdx_license_key: LicenseRef-scancode-guile-exception-2.0 +spdx_license_key: harbour-exception +other_spdx_license_keys: + - LicenseRef-scancode-guile-exception-2.0 other_urls: - http://www.gnu.org/licenses/gpl-2.0.txt + - https://github.com/harbour/core/blob/master/LICENSE.txt#L44-L66 standard_notice: | This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/src/licensedcode/data/licenses/independent-modules-exception.LICENSE b/src/licensedcode/data/licenses/independent-modules-exception.LICENSE new file mode 100644 index 00000000000..39338c1db28 --- /dev/null +++ b/src/licensedcode/data/licenses/independent-modules-exception.LICENSE @@ -0,0 +1,28 @@ +--- +key: independent-modules-exception +short_name: Independent Module Linking exception +name: Independent Module Linking exception +is_exception: yes +spdx_license_key: Independent-modules-exception +other_urls: + - https://gitlab.com/freepascal.org/fpc/source/-/blob/release_3_2_2/rtl/COPYING.FPC +--- + +This is the file COPYING.FPC, it applies to the Free Pascal Run-Time Library +(RTL) and packages (packages) distributed by members of the Free Pascal +Development Team. + +The source code of the Free Pascal Runtime Libraries and packages are +distributed under the Library GNU General Public License +(see the file COPYING) with the following modification: + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent modules, +and to copy and distribute the resulting executable under terms of your choice, +provided that you also meet, for each linked independent module, the terms +and conditions of the license of that module. An independent module is a module +which is not derived from or based on this library. If you modify this +library, you may extend this exception to your version of the library, but you are +not obligated to do so. If you do not wish to do so, delete this exception +statement from your version. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/inno-setup.LICENSE b/src/licensedcode/data/licenses/inno-setup.LICENSE index 50f941ba54f..15d04cbc780 100644 --- a/src/licensedcode/data/licenses/inno-setup.LICENSE +++ b/src/licensedcode/data/licenses/inno-setup.LICENSE @@ -5,7 +5,9 @@ name: Inno Setup License category: Permissive owner: jrsoftware.org homepage_url: http://www.jrsoftware.org/files/is/license.txt -spdx_license_key: LicenseRef-scancode-inno-setup +spdx_license_key: InnoSetup +other_spdx_license_keys: + - LicenseRef-scancode-inno-setup text_urls: - http://www.jrsoftware.org/files/is/license.txt ignorable_copyrights: diff --git a/src/licensedcode/data/licenses/mips.LICENSE b/src/licensedcode/data/licenses/mips.LICENSE new file mode 100644 index 00000000000..ef41b0db1d4 --- /dev/null +++ b/src/licensedcode/data/licenses/mips.LICENSE @@ -0,0 +1,16 @@ +--- +key: mips +short_name: MIPS License +name: MIPS License +notes: | + Added in SPDX license list 3.25 + This was previously the license rule: other-permissive_116.RULE +spdx_license_key: MIPS +other_urls: + - https://sourceware.org/cgit/binutils-gdb/tree/include/coff/sym.h#n11 +--- + +Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc. +MIPS Computer Systems, Inc. grants reproduction and use +rights to all parties, PROVIDED that this comment is +maintained in the copy. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE b/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE new file mode 100644 index 00000000000..198bf19afe2 --- /dev/null +++ b/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE @@ -0,0 +1,84 @@ +--- +key: sendmail-open-source-1.1 +short_name: Sendmail Open Source License v1.1 +name: Sendmail Open Source License v1.1 +spdx_license_key: Sendmail-Open-Source-1.1 +other_urls: + - https://github.com/trusteddomainproject/OpenDMARC/blob/master/LICENSE.Sendmail +--- + +SENDMAIL OPEN SOURCE LICENSE + +The following license terms and conditions apply to this open source +software ("Software"), unless a different license is obtained directly +from Sendmail, Inc. ("Sendmail") located at 6475 Christie Ave, Suite 350, +Emeryville, CA 94608, USA. + +Use, modification and redistribution (including distribution of any +modified or derived work) of the Software in source and binary forms is +permitted only if each of the following conditions of 1-6 are met: + +1. Redistributions of the Software qualify as "freeware" or "open + source software" under one of the following terms: + + (a) Redistributions are made at no charge beyond the reasonable + cost of materials and delivery; or + + (b) Redistributions are accompanied by a copy of the modified + Source Code (on an acceptable machine-readable medium) or by an + irrevocable offer to provide a copy of the modified Source Code + (on an acceptable machine-readable medium) for up to three years + at the cost of materials and delivery. Such redistributions must + allow further use, modification, and redistribution of the Source + Code under substantially the same terms as this license. For + the purposes of redistribution "Source Code" means the complete + human-readable, compilable, linkable, and operational source + code of the redistributed module(s) including all modifications. + +2. Redistributions of the Software Source Code must retain the + copyright notices as they appear in each Source Code file, these + license terms and conditions, and the disclaimer/limitation of + liability set forth in paragraph 6 below. Redistributions of the + Software Source Code must also comply with the copyright notices + and/or license terms and conditions imposed by contributors on + embedded code. The contributors' license terms and conditions + and/or copyright notices are contained in the Source Code + distribution. + +3. Redistributions of the Software in binary form must reproduce the + Copyright Notice described below, these license terms and conditions, + and the disclaimer/limitation of liability set forth in paragraph + 6 below, in the documentation and/or other materials provided with + the binary distribution. For the purposes of binary distribution, + "Copyright Notice" refers to the following language: "Copyright (c) + 1998-2009 Sendmail, Inc. All rights reserved." + +4. Neither the name, trademark or logo of Sendmail, Inc. (including + without limitation its subsidiaries or affiliates) or its contributors + may be used to endorse or promote products, or software or services + derived from this Software without specific prior written permission. + The name "sendmail" is a registered trademark and service mark of + Sendmail, Inc. + +5. We reserve the right to cancel this license if you do not comply with + the terms. This license is governed by California law and both of us + agree that for any dispute arising out of or relating to this Software, + that jurisdiction and venue is proper in San Francisco or Alameda + counties. These license terms and conditions reflect the complete + agreement for the license of the Software (which means this supercedes + prior or contemporaneous agreements or representations). If any term + or condition under this license is found to be invalid, the remaining + terms and conditions still apply. + +6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY + SENDMAIL AND ITS CONTRIBUTORS "AS IS" WITHOUT WARRANTY OF ANY KIND + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A + PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. IN NO EVENT SHALL SENDMAIL + OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + WITHOUT LIMITATION NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/smail-gpl.LICENSE b/src/licensedcode/data/licenses/smail-gpl.LICENSE index 6e5997ff7f5..9fba8538d78 100644 --- a/src/licensedcode/data/licenses/smail-gpl.LICENSE +++ b/src/licensedcode/data/licenses/smail-gpl.LICENSE @@ -5,9 +5,13 @@ name: SMAIL General Public License category: Copyleft owner: SMAIL Project homepage_url: https://gitweb.gentoo.org/repo/gentoo.git/plain/licenses/SMAIL -spdx_license_key: LicenseRef-scancode-smail-gpl +spdx_license_key: SMAIL-GPL +other_spdx_license_keys: + - LicenseRef-scancode-smail-gpl text_urls: - https://gitweb.gentoo.org/repo/gentoo.git/plain/licenses/SMAIL +other_urls: + - https://sources.debian.org/copyright/license/debianutils/4.11.2/ ignorable_copyrights: - Copyright (c) 1988 Landon Curt Noll & Ronald S. Karr - Copyright (c) 1992 Ronald S. Karr diff --git a/src/licensedcode/data/licenses/stlport-4.5.LICENSE b/src/licensedcode/data/licenses/stlport-4.5.LICENSE index 8607a3c4824..976403506d6 100644 --- a/src/licensedcode/data/licenses/stlport-4.5.LICENSE +++ b/src/licensedcode/data/licenses/stlport-4.5.LICENSE @@ -5,7 +5,11 @@ name: STLport License v4.5 category: Permissive owner: STLport Consulting notes: stlport-4.5 and mozilla-gc are mostly the same -spdx_license_key: LicenseRef-scancode-stlport-4.5 +spdx_license_key: Boehm-GC-without-fee +other_spdx_license_keys: + - LicenseRef-scancode-stlport-4.5 +other_urls: + - https://github.com/MariaDB/server/blob/11.6/libmysqld/lib_sql.cc --- This material is provided "as is", with absolutely no warranty expressed diff --git a/src/licensedcode/data/licenses/thirdeye.LICENSE b/src/licensedcode/data/licenses/thirdeye.LICENSE new file mode 100644 index 00000000000..7bd17ac6d50 --- /dev/null +++ b/src/licensedcode/data/licenses/thirdeye.LICENSE @@ -0,0 +1,16 @@ +--- +key: thirdeye +short_name: ThirdEye License +name: ThirdEye License +spdx_license_key: ThirdEye +other_urls: + - https://sourceware.org/cgit/binutils-gdb/tree/include/coff/symconst.h#n11 +--- + +(C) Copyright 1984 by Third Eye Software, Inc. + +Third Eye Software, Inc. grants reproduction and use rights to +all parties, PROVIDED that this comment is maintained in the copy. + +Third Eye makes no claims about the applicability of this +symbol table to a particular use. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/trustedqsl.LICENSE b/src/licensedcode/data/licenses/trustedqsl.LICENSE new file mode 100644 index 00000000000..cd0c3c0b61f --- /dev/null +++ b/src/licensedcode/data/licenses/trustedqsl.LICENSE @@ -0,0 +1,67 @@ +--- +key: trustedqsl +short_name: TrustedQSL License +name: TrustedQSL License +spdx_license_key: TrustedQSL +other_urls: + - https://sourceforge.net/p/trustedqsl/tqsl/ci/master/tree/LICENSE.txt +--- + +Copyright (C) 2001-2015 American Radio Relay League, Inc. All rights +reserved. + +Portions (C) 2003-2023 The TrustedQSL Developers. Please see the AUTHORS.txt +file for contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Any redistribution of source code must retain the above copyright +notice, this list of conditions and the disclaimer shown in +Paragraph 5 (below). + +2. Redistribution in binary form must reproduce the above copyright +notice, this list of conditions and the disclaimer shown in +Paragraph 5 (below) in the documentation and/or other materials +provided with the distribution. + +3. Products derived from or including this software may not use +"Logbook of the World" or "LoTW" or any other American Radio Relay +League, Incorporated trademarks or servicemarks in their names +without prior written permission of the ARRL. See Paragraph 6 +(below) for contact information. + +4. Use of this software does not imply endorsement by ARRL of +products derived from or including this software and vendors may not +claim such endorsement. + +5. Disclaimer: This software is provided "as-is" without +representation, guarantee or warranty of any kind, either express or +implied, including but not limited to the implied warranties of +merchantability or of fitness for a particular purpose. The entire +risk as to the quality and performance of the software is solely +with you. Should the software prove defective, you (and not the +American Radio Relay League, its officers, directors, employees or +agents) assume the entire cost of all necessary servicing, repair or +correction. In no event will ARRL be liable to you or to any third +party for any damages, whether direct or indirect, including lost +profits, lost savings, or other incidental or consequential damages +arising out of the use or inability to use such software, regardless +of whether ARRL has been advised of the possibility of such damages. + +6. Contact information: + +American Radio Relay League, Inc. +Attn: Logbook of the World Manager +225 Main St +Newington, CT 06111 +voice: 860-594-0200 +fax: 860-594-0259 +email: logbook@arrl.org +Worldwide Web: www.arrl.org + +This software consists of voluntary contributions made by many +individuals on behalf of the ARRL. More information on the "Logbook +of The World" project and the ARRL is available from the ARRL Web +site at www.arrl.org. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/wwl.LICENSE b/src/licensedcode/data/licenses/wwl.LICENSE new file mode 100644 index 00000000000..a8b985f98b3 --- /dev/null +++ b/src/licensedcode/data/licenses/wwl.LICENSE @@ -0,0 +1,14 @@ +--- +key: wwl +short_name: WWL License +name: WWL License +spdx_license_key: wwl +other_urls: + - http://www.db.net/downloads/wwl+db-1.3.tgz +--- + +db@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this code, except you may not +license it under any form of the GPL. +A postcard or QSL card showing me you appreciate +this code would be nice. Diane Bruce va3db \ No newline at end of file diff --git a/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE b/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE index d198c6d623a..6e212e3960c 100644 --- a/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE +++ b/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE @@ -3,7 +3,11 @@ license_expression: lgpl-2.1 WITH broadcom-linking-exception-2.0 is_license_notice: yes referenced_filenames: - COPYING -notes: found in the freepascal compiler +notes: + found in the freepascal compiler + Added in SPDX license list 3.26 + Replaced by license: independent-modules-exception.LICENSE +is_deprecated: yes --- The source code of the Free Pascal Runtime Libraries and packages are diff --git a/src/licensedcode/data/rules/other-permissive_116.RULE b/src/licensedcode/data/rules/other-permissive_116.RULE index c73ade8513c..0390772ae58 100644 --- a/src/licensedcode/data/rules/other-permissive_116.RULE +++ b/src/licensedcode/data/rules/other-permissive_116.RULE @@ -1,7 +1,11 @@ --- license_expression: other-permissive is_license_text: yes +is_deprecated: yes relevance: 100 +notes: | + Added in SPDX license list 3.26 + Replaced by license: mips.LICENSE --- grants reproduction and use | diff --git a/src/licensedcode/data/rules/other-permissive_or_gpl-1.0-plus_2.RULE b/src/licensedcode/data/rules/other-permissive_or_gpl-1.0-plus_2.RULE index 1f11977f525..8b24f46830a 100644 --- a/src/licensedcode/data/rules/other-permissive_or_gpl-1.0-plus_2.RULE +++ b/src/licensedcode/data/rules/other-permissive_or_gpl-1.0-plus_2.RULE @@ -1,6 +1,10 @@ --- license_expression: other-permissive OR gpl-1.0-plus is_license_notice: yes +is_deprecated: yes +notes: | + Added in SPDX license list 3.26 + Replaced by license: generic-xts.LICENSE --- * Permission to use, copy, and modify this software with or without fee From a5250833af0a589289e849b881a24659222850b8 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Thu, 9 Jan 2025 20:30:16 +0530 Subject: [PATCH 22/29] Add categories, owners and other updates Signed-off-by: Ayan Sinha Mahapatra --- .../data/licenses/any-osi-perl-modules.LICENSE | 4 ++++ .../licenses/cgal-linking-exception.LICENSE | 4 ++++ .../data/licenses/docbook-stylesheet.LICENSE | 8 ++------ .../data/licenses/generic-xts.LICENSE | 5 ++--- .../gpl-3.0-389-ds-base-exception.LICENSE | 4 ++++ ...ndependent-module-linking-exception.LICENSE | 5 ++++- src/licensedcode/data/licenses/mips.LICENSE | 3 ++- .../licenses/sendmail-open-source-1.1.LICENSE | 6 ++++++ .../data/licenses/thirdeye.LICENSE | 4 ++-- .../data/licenses/trustedqsl.LICENSE | 12 ++++++------ src/licensedcode/data/licenses/wwl.LICENSE | 5 +++++ .../data/rules/click-license_1.RULE | 10 ++++++++++ ...ndependent-module-linking-exception_1.RULE} | 9 ++------- ..._with_broadcom-linking-exception-2.0_1.RULE | 2 +- .../stable_copyright-detailed.expected.yml | 18 +++++++++--------- .../copyright-detailed.expected.yml | 6 +++--- 16 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 src/licensedcode/data/rules/click-license_1.RULE rename src/licensedcode/data/{licenses/independent-modules-exception.LICENSE => rules/independent-module-linking-exception_1.RULE} (78%) diff --git a/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE b/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE index bdccf7234a1..9f73e324f97 100644 --- a/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE +++ b/src/licensedcode/data/licenses/any-osi-perl-modules.LICENSE @@ -2,11 +2,15 @@ key: any-osi-perl-modules short_name: Any OSI Perl Modules name: Any OSI License - Perl Modules +category: Unstated License +owner: Unspecified spdx_license_key: any-OSI-perl-modules other_urls: - https://metacpan.org/release/JUERD/Exporter-Tidy-0.09/view/Tidy.pm#LICENSE - https://metacpan.org/pod/Qmail::Deliverable::Client#LICENSE - https://metacpan.org/pod/Net::MQTT::Simple#LICENSE +ignorable_urls: + - http://www.opensource.org/licenses/alphabetical --- This software may be redistributed under the terms of the GPL, LGPL, diff --git a/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE index 22bc8f0553b..34dfaa891ca 100644 --- a/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE +++ b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE @@ -2,11 +2,15 @@ key: cgal-linking-exception short_name: CGAL Linking Exception name: CGAL Linking Exception +category: Copyleft Limited +owner: cgal.org is_exception: yes spdx_license_key: CGAL-linking-exception other_urls: - https://github.com/openscad/openscad/blob/openscad-2021.01/COPYING#L3 - https://github.com/floriankirsch/OpenCSG/blob/opencsg-1-4-2-release/license.txt#L3 +ignorable_urls: + - http://www.cgal.org/ --- As a special exception, you have permission to link this library diff --git a/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE b/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE index 35dff87b998..8b4452388c3 100644 --- a/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE +++ b/src/licensedcode/data/licenses/docbook-stylesheet.LICENSE @@ -3,16 +3,12 @@ key: docbook-stylesheet short_name: DocBook Stylesheet License name: DocBook Stylesheet License spdx_license_key: DocBook-Stylesheet +category: Permissive +owner: OASIS other_urls: - http://www.docbook.org/xml/5.0/docbook-5.0.zip --- -Copyright 2005 Norman Walsh, Sun Microsystems, -Inc., and the Organization for the Advancement -of Structured Information Standards (OASIS). - -Release: $Id: db4-upgrade.xsl 8905 2010-09-12 11:47:07Z bobstayton $ - Permission to use, copy, modify and distribute this stylesheet and its accompanying documentation for any purpose and without fee is hereby granted in perpetuity, provided that diff --git a/src/licensedcode/data/licenses/generic-xts.LICENSE b/src/licensedcode/data/licenses/generic-xts.LICENSE index 146a3eb82eb..fc11aa9091a 100644 --- a/src/licensedcode/data/licenses/generic-xts.LICENSE +++ b/src/licensedcode/data/licenses/generic-xts.LICENSE @@ -2,14 +2,13 @@ key: generic-xts short_name: Generic XTS License name: Generic XTS License +category: Permissive +owner: Unspecified spdx_license_key: generic-xts other_urls: - https://github.com/mhogomchungu/zuluCrypt/blob/master/external_libraries/tcplay/generic_xts.c --- -Copyright (C) 2008, Damien Miller -Copyright (C) 2011, Alex Hornung - Permission to use, copy, and modify this software with or without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or diff --git a/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE b/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE index d7c0bc59a9d..efca870a858 100644 --- a/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE +++ b/src/licensedcode/data/licenses/gpl-3.0-389-ds-base-exception.LICENSE @@ -2,8 +2,12 @@ key: gpl-3.0-389-ds-base-exception short_name: GPL-3.0 389 DS Base Exception name: GPL-3.0 389 DS Base Exception +category: Copyleft Limited +owner: Free Software Foundation (FSF) is_exception: yes spdx_license_key: GPL-3.0-389-ds-base-exception +ignorable_urls: + - https://www.openssl.org/source/license.html --- Additional permission under GPLv3 section 7: diff --git a/src/licensedcode/data/licenses/independent-module-linking-exception.LICENSE b/src/licensedcode/data/licenses/independent-module-linking-exception.LICENSE index 9af18dca5f0..0624ce6e83a 100644 --- a/src/licensedcode/data/licenses/independent-module-linking-exception.LICENSE +++ b/src/licensedcode/data/licenses/independent-module-linking-exception.LICENSE @@ -6,9 +6,12 @@ category: Copyleft Limited owner: Unspecified notes: this is typically seen with the LGPL but is not L/GPL specific is_exception: yes -spdx_license_key: LicenseRef-scancode-indie-module-linking-exception +spdx_license_key: Independent-modules-exception other_spdx_license_keys: + - LicenseRef-scancode-indie-module-linking-exception - LicenseRef-scancode-independent-module-linking-exception +other_urls: + - https://gitlab.com/freepascal.org/fpc/source/-/blob/release_3_2_2/rtl/COPYING.FPC --- As a special exception, the copyright holders of this library give you diff --git a/src/licensedcode/data/licenses/mips.LICENSE b/src/licensedcode/data/licenses/mips.LICENSE index ef41b0db1d4..8aeec59f83b 100644 --- a/src/licensedcode/data/licenses/mips.LICENSE +++ b/src/licensedcode/data/licenses/mips.LICENSE @@ -2,6 +2,8 @@ key: mips short_name: MIPS License name: MIPS License +category: Permissive +owner: MIPS Computer Systems, Inc. notes: | Added in SPDX license list 3.25 This was previously the license rule: other-permissive_116.RULE @@ -10,7 +12,6 @@ other_urls: - https://sourceware.org/cgit/binutils-gdb/tree/include/coff/sym.h#n11 --- -Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc. MIPS Computer Systems, Inc. grants reproduction and use rights to all parties, PROVIDED that this comment is maintained in the copy. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE b/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE index 198bf19afe2..1687b44bfd6 100644 --- a/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE +++ b/src/licensedcode/data/licenses/sendmail-open-source-1.1.LICENSE @@ -2,9 +2,15 @@ key: sendmail-open-source-1.1 short_name: Sendmail Open Source License v1.1 name: Sendmail Open Source License v1.1 +category: Permissive +owner: Sendmail spdx_license_key: Sendmail-Open-Source-1.1 other_urls: - https://github.com/trusteddomainproject/OpenDMARC/blob/master/LICENSE.Sendmail +ignorable_copyrights: + - Copyright (c) 1998-2009 Sendmail, Inc. +ignorable_holders: + - Sendmail, Inc. --- SENDMAIL OPEN SOURCE LICENSE diff --git a/src/licensedcode/data/licenses/thirdeye.LICENSE b/src/licensedcode/data/licenses/thirdeye.LICENSE index 7bd17ac6d50..8a909f3c8a6 100644 --- a/src/licensedcode/data/licenses/thirdeye.LICENSE +++ b/src/licensedcode/data/licenses/thirdeye.LICENSE @@ -2,13 +2,13 @@ key: thirdeye short_name: ThirdEye License name: ThirdEye License +category: Permissive +owner: Third Eye Software, Inc. spdx_license_key: ThirdEye other_urls: - https://sourceware.org/cgit/binutils-gdb/tree/include/coff/symconst.h#n11 --- -(C) Copyright 1984 by Third Eye Software, Inc. - Third Eye Software, Inc. grants reproduction and use rights to all parties, PROVIDED that this comment is maintained in the copy. diff --git a/src/licensedcode/data/licenses/trustedqsl.LICENSE b/src/licensedcode/data/licenses/trustedqsl.LICENSE index cd0c3c0b61f..0d1ff7f9017 100644 --- a/src/licensedcode/data/licenses/trustedqsl.LICENSE +++ b/src/licensedcode/data/licenses/trustedqsl.LICENSE @@ -2,17 +2,17 @@ key: trustedqsl short_name: TrustedQSL License name: TrustedQSL License +category: Permissive +owner: TrustedQSL Developers spdx_license_key: TrustedQSL other_urls: - https://sourceforge.net/p/trustedqsl/tqsl/ci/master/tree/LICENSE.txt +ignorable_urls: + - http://www.arrl.org/ +ignorable_emails: + - logbook@arrl.org --- -Copyright (C) 2001-2015 American Radio Relay League, Inc. All rights -reserved. - -Portions (C) 2003-2023 The TrustedQSL Developers. Please see the AUTHORS.txt -file for contributors. - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/licensedcode/data/licenses/wwl.LICENSE b/src/licensedcode/data/licenses/wwl.LICENSE index a8b985f98b3..0fc0497cd6c 100644 --- a/src/licensedcode/data/licenses/wwl.LICENSE +++ b/src/licensedcode/data/licenses/wwl.LICENSE @@ -2,9 +2,14 @@ key: wwl short_name: WWL License name: WWL License +category: Permissive +owner: Diane Bruce spdx_license_key: wwl other_urls: - http://www.db.net/downloads/wwl+db-1.3.tgz + - https://tracker.debian.org/media/packages/w/wwl/copyright-1.3%2Bdb-2 +ignorable_emails: + - db@FreeBSD.ORG --- db@FreeBSD.ORG wrote this file. As long as you retain this notice you diff --git a/src/licensedcode/data/rules/click-license_1.RULE b/src/licensedcode/data/rules/click-license_1.RULE new file mode 100644 index 00000000000..49335544899 --- /dev/null +++ b/src/licensedcode/data/rules/click-license_1.RULE @@ -0,0 +1,10 @@ +--- +license_expression: click-license +is_license_notice: yes +--- + +Portions of this software are subject to the license below. The relevant +source files are clearly marked; they refer to this file using the phrase +"the {{Click LICENSE}} file". This license is an MIT license, plus a clause +(taken from the W3C license) requiring prior written permission to use our +names in publicity. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/independent-modules-exception.LICENSE b/src/licensedcode/data/rules/independent-module-linking-exception_1.RULE similarity index 78% rename from src/licensedcode/data/licenses/independent-modules-exception.LICENSE rename to src/licensedcode/data/rules/independent-module-linking-exception_1.RULE index 39338c1db28..2da90686646 100644 --- a/src/licensedcode/data/licenses/independent-modules-exception.LICENSE +++ b/src/licensedcode/data/rules/independent-module-linking-exception_1.RULE @@ -1,11 +1,6 @@ --- -key: independent-modules-exception -short_name: Independent Module Linking exception -name: Independent Module Linking exception -is_exception: yes -spdx_license_key: Independent-modules-exception -other_urls: - - https://gitlab.com/freepascal.org/fpc/source/-/blob/release_3_2_2/rtl/COPYING.FPC +license_expression: independent-module-linking-exception +is_license_text: yes --- This is the file COPYING.FPC, it applies to the Free Pascal Run-Time Library diff --git a/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE b/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE index 6e212e3960c..4f72fb54fac 100644 --- a/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE +++ b/src/licensedcode/data/rules/lgpl-2.1_with_broadcom-linking-exception-2.0_1.RULE @@ -3,7 +3,7 @@ license_expression: lgpl-2.1 WITH broadcom-linking-exception-2.0 is_license_notice: yes referenced_filenames: - COPYING -notes: +notes: | found in the freepascal compiler Added in SPDX license list 3.26 Replaced by license: independent-modules-exception.LICENSE diff --git a/tests/packagedcode/data/debian/copyright/debian-2019-11-15/main/m/mariadb-10.3/stable_copyright-detailed.expected.yml b/tests/packagedcode/data/debian/copyright/debian-2019-11-15/main/m/mariadb-10.3/stable_copyright-detailed.expected.yml index 6f73ed8d2d4..42b3fffe675 100644 --- a/tests/packagedcode/data/debian/copyright/debian-2019-11-15/main/m/mariadb-10.3/stable_copyright-detailed.expected.yml +++ b/tests/packagedcode/data/debian/copyright/debian-2019-11-15/main/m/mariadb-10.3/stable_copyright-detailed.expected.yml @@ -138,13 +138,13 @@ other_license_expression_spdx: (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-or-l AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND (LGPL-2.0-or-later AND LGPL-2.0-only) AND (LGPL-2.0-or-later AND LGPL-2.0-only) - AND LicenseRef-scancode-stlport-4.5 AND LicenseRef-scancode-public-domain AND (GPL-2.0-only - AND GPL-2.0-only) AND ((GPL-2.0-only AND GPL-2.0-only) OR (Artistic-1.0-Perl AND Artistic-1.0-Perl)) - AND LicenseRef-scancode-public-domain AND BSD-3-Clause AND (GPL-2.0-only AND GPL-2.0-only) - AND (GPL-2.0-or-later AND GPL-2.0-or-later) AND (GPL-3.0-or-later AND GPL-3.0-or-later) AND - (LGPL-2.1-or-later AND LGPL-2.1-or-later) AND (GPL-2.0-or-later AND GPL-2.0-or-later) AND - (X11 AND LicenseRef-scancode-public-domain) AND BSD-3-Clause AND (GPL-2.0-only AND GPL-2.0-only) - AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) + AND Boehm-GC-without-fee AND LicenseRef-scancode-public-domain AND (GPL-2.0-only AND GPL-2.0-only) + AND ((GPL-2.0-only AND GPL-2.0-only) OR (Artistic-1.0-Perl AND Artistic-1.0-Perl)) AND LicenseRef-scancode-public-domain + AND BSD-3-Clause AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-or-later AND GPL-2.0-or-later) + AND (GPL-3.0-or-later AND GPL-3.0-or-later) AND (LGPL-2.1-or-later AND LGPL-2.1-or-later) + AND (GPL-2.0-or-later AND GPL-2.0-or-later) AND (X11 AND LicenseRef-scancode-public-domain) + AND BSD-3-Clause AND (GPL-2.0-only AND GPL-2.0-only) AND (GPL-2.0-only AND GPL-2.0-only) AND + (GPL-2.0-only AND GPL-2.0-only) license_detections: [] other_license_detections: - license_expression: other-copyleft @@ -304,10 +304,10 @@ other_license_detections: version 2.2 of Bison. identifier: gpl_3_0_plus_with_bison_exception_2_2-637d6c30-89c5-8764-b189-8bb20227ccfc - license_expression: stlport-4.5 - license_expression_spdx: LicenseRef-scancode-stlport-4.5 + license_expression_spdx: Boehm-GC-without-fee matches: - license_expression: stlport-4.5 - license_expression_spdx: LicenseRef-scancode-stlport-4.5 + license_expression_spdx: Boehm-GC-without-fee from_file: start_line: 734 end_line: 741 diff --git a/tests/packagedcode/data/debian/copyright/debian-slim-2021-04-07/usr/share/doc/debianutils/copyright-detailed.expected.yml b/tests/packagedcode/data/debian/copyright/debian-slim-2021-04-07/usr/share/doc/debianutils/copyright-detailed.expected.yml index 03e64ded0d4..84f20291d7b 100644 --- a/tests/packagedcode/data/debian/copyright/debian-slim-2021-04-07/usr/share/doc/debianutils/copyright-detailed.expected.yml +++ b/tests/packagedcode/data/debian/copyright/debian-slim-2021-04-07/usr/share/doc/debianutils/copyright-detailed.expected.yml @@ -1,7 +1,7 @@ declared_license: declared_license_expression: (gpl-2.0-plus AND public-domain) AND smail-gpl declared_license_expression_spdx: (GPL-2.0-or-later AND LicenseRef-scancode-public-domain) AND - LicenseRef-scancode-smail-gpl + SMAIL-GPL other_license_expression: other_license_expression_spdx: license_detections: @@ -27,10 +27,10 @@ license_detections: which is in the public domain. identifier: gpl_2_0_plus_and_public_domain-e8510ebe-e9a6-c0d1-ae7e-42280922b32a - license_expression: smail-gpl - license_expression_spdx: LicenseRef-scancode-smail-gpl + license_expression_spdx: SMAIL-GPL matches: - license_expression: smail-gpl - license_expression_spdx: LicenseRef-scancode-smail-gpl + license_expression_spdx: SMAIL-GPL from_file: start_line: 18 end_line: 161 From bb7ac7d09d16dd99e0e7f2918e0e0a440c445014 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Thu, 9 Jan 2025 23:11:18 +0530 Subject: [PATCH 23/29] Update owners and rules from feedback Signed-off-by: Ayan Sinha Mahapatra --- .../licenses/cgal-linking-exception.LICENSE | 2 +- .../data/licenses/generic-xts.LICENSE | 2 +- src/licensedcode/data/licenses/mips.LICENSE | 2 +- .../data/licenses/thirdeye.LICENSE | 2 +- ...ndependent-module-linking-exception_1.RULE | 28 +++++++++++++++++++ ...dependent-module-linking-exception_2.RULE} | 9 ++++-- 6 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_1.RULE rename src/licensedcode/data/rules/{independent-module-linking-exception_1.RULE => lgpl-2.0-plus_with_independent-module-linking-exception_2.RULE} (82%) diff --git a/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE index 34dfaa891ca..174d9e2456f 100644 --- a/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE +++ b/src/licensedcode/data/licenses/cgal-linking-exception.LICENSE @@ -3,7 +3,7 @@ key: cgal-linking-exception short_name: CGAL Linking Exception name: CGAL Linking Exception category: Copyleft Limited -owner: cgal.org +owner: CGAL Project is_exception: yes spdx_license_key: CGAL-linking-exception other_urls: diff --git a/src/licensedcode/data/licenses/generic-xts.LICENSE b/src/licensedcode/data/licenses/generic-xts.LICENSE index fc11aa9091a..57cfe178d08 100644 --- a/src/licensedcode/data/licenses/generic-xts.LICENSE +++ b/src/licensedcode/data/licenses/generic-xts.LICENSE @@ -3,7 +3,7 @@ key: generic-xts short_name: Generic XTS License name: Generic XTS License category: Permissive -owner: Unspecified +owner: zulucrypt Project spdx_license_key: generic-xts other_urls: - https://github.com/mhogomchungu/zuluCrypt/blob/master/external_libraries/tcplay/generic_xts.c diff --git a/src/licensedcode/data/licenses/mips.LICENSE b/src/licensedcode/data/licenses/mips.LICENSE index 8aeec59f83b..d89bd8077a7 100644 --- a/src/licensedcode/data/licenses/mips.LICENSE +++ b/src/licensedcode/data/licenses/mips.LICENSE @@ -3,7 +3,7 @@ key: mips short_name: MIPS License name: MIPS License category: Permissive -owner: MIPS Computer Systems, Inc. +owner: MIPS Computer Systems notes: | Added in SPDX license list 3.25 This was previously the license rule: other-permissive_116.RULE diff --git a/src/licensedcode/data/licenses/thirdeye.LICENSE b/src/licensedcode/data/licenses/thirdeye.LICENSE index 8a909f3c8a6..1bab43240b2 100644 --- a/src/licensedcode/data/licenses/thirdeye.LICENSE +++ b/src/licensedcode/data/licenses/thirdeye.LICENSE @@ -3,7 +3,7 @@ key: thirdeye short_name: ThirdEye License name: ThirdEye License category: Permissive -owner: Third Eye Software, Inc. +owner: Third Eye Software spdx_license_key: ThirdEye other_urls: - https://sourceware.org/cgit/binutils-gdb/tree/include/coff/symconst.h#n11 diff --git a/src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_1.RULE b/src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_1.RULE new file mode 100644 index 00000000000..f46324f6b3b --- /dev/null +++ b/src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_1.RULE @@ -0,0 +1,28 @@ +--- +license_expression: lgpl-2.0-plus WITH independent-module-linking-exception +is_license_notice: yes +minimum_coverage: 90 +referenced_filenames: + - COPYING +--- + +The source code of the Free Pascal Runtime Libraries and packages are +distributed under the {{Library GNU General Public License}} +(see the file COPYING) with the following modification: + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent modules, +and to copy and distribute the resulting executable under terms of your choice, +provided that you also meet, for each linked independent module, the terms +and conditions of the license of that module. An independent module is a module +which is not derived from or based on this library. If you modify this +library, you may extend this exception to your version of the library, but you are +not obligated to do so. If you do not wish to do so, delete this exception +statement from your version. + +If you didn't receive a copy of the file COPYING, contact: + Free Software Foundation + 675 Mass Ave + Cambridge, MA 02139 + USA \ No newline at end of file diff --git a/src/licensedcode/data/rules/independent-module-linking-exception_1.RULE b/src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_2.RULE similarity index 82% rename from src/licensedcode/data/rules/independent-module-linking-exception_1.RULE rename to src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_2.RULE index 2da90686646..13e05e6bd40 100644 --- a/src/licensedcode/data/rules/independent-module-linking-exception_1.RULE +++ b/src/licensedcode/data/rules/lgpl-2.0-plus_with_independent-module-linking-exception_2.RULE @@ -1,6 +1,9 @@ --- -license_expression: independent-module-linking-exception -is_license_text: yes +license_expression: lgpl-2.0-plus WITH independent-module-linking-exception +is_license_notice: yes +minimum_coverage: 90 +referenced_filenames: + - COPYING --- This is the file COPYING.FPC, it applies to the Free Pascal Run-Time Library @@ -8,7 +11,7 @@ This is the file COPYING.FPC, it applies to the Free Pascal Run-Time Library Development Team. The source code of the Free Pascal Runtime Libraries and packages are -distributed under the Library GNU General Public License +distributed under the {{Library GNU General Public License}} (see the file COPYING) with the following modification: As a special exception, the copyright holders of this library give you From 4a45d5b3192dc361fb03a362c501a9ede0c43923 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Fri, 10 Jan 2025 01:27:32 +0530 Subject: [PATCH 24/29] Add more licenses from dejacode These were added by @DennisClark Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/4080 Signed-off-by: Ayan Sinha Mahapatra --- .../data/licenses/socketxx-2003.LICENSE | 21 ++ .../data/licenses/teleport-ce-2024.LICENSE | 193 ++++++++++++++++++ .../data/rules/other-permissive_1066.RULE | 2 + 3 files changed, 216 insertions(+) create mode 100644 src/licensedcode/data/licenses/socketxx-2003.LICENSE create mode 100644 src/licensedcode/data/licenses/teleport-ce-2024.LICENSE diff --git a/src/licensedcode/data/licenses/socketxx-2003.LICENSE b/src/licensedcode/data/licenses/socketxx-2003.LICENSE new file mode 100644 index 00000000000..e6240a618b8 --- /dev/null +++ b/src/licensedcode/data/licenses/socketxx-2003.LICENSE @@ -0,0 +1,21 @@ +--- +key: socketxx-2003 +short_name: Socketxx License 2003 +name: Socketxx License 2003 +category: Permissive +owner: Herbert Straub +homepage_url: https://github.com/hstraub/socketxx/blob/master/COPYING +spdx_license_key: LicenseRef-scancode-socketxx-2003 +text_urls: + - https://github.com/malaterre/socketxx-1/blob/master/COPYING +standard_notice: | + Copyright Notice: + ----------------- + Portions Copyright (C) 2002-2003 Herbert Straub for all my changes (see + ChangeLog) +--- + +Permission is granted to use at your own risk and distribute this software +in source and binary forms provided the above copyright notice and this +paragraph are preserved on all copies. This software is provided "as is" +with no express or implied warranty. \ No newline at end of file diff --git a/src/licensedcode/data/licenses/teleport-ce-2024.LICENSE b/src/licensedcode/data/licenses/teleport-ce-2024.LICENSE new file mode 100644 index 00000000000..8c4898f7426 --- /dev/null +++ b/src/licensedcode/data/licenses/teleport-ce-2024.LICENSE @@ -0,0 +1,193 @@ +--- +key: teleport-ce-2024 +short_name: Teleport Community Edition License 2024 +name: Teleport Community Edition License 2024 +category: Proprietary Free +owner: Teleport +homepage_url: https://github.com/gravitational/teleport/blob/master/build.assets/LICENSE-community +spdx_license_key: LicenseRef-scancode-teleport-ce-2024 +ignorable_urls: + - https://github.com/gravitational/teleport/blob/master/build.assets/LICENSE-community +--- + +Teleport Community Edition License + +THE TELEPORT COMMUNITY EDITION IS AVAILABLE ONLY TO ORGANIZATIONS THAT HAVE +LESS THAN ONE HUNDRED (100) EMPLOYEES AND LESS THAN TEN MILLION DOLLARS +($10,000,000.00) IN ANNUAL REVENUE. PROVIDED THE ORGANIZATION MEETS THESE +REQUIREMENTS, THE TELEPORT COMMUNITY EDITION IS MADE AVAILABLE UNDER THIS +LICENSE. + +INTRODUCTORY NOTE: THIS LICENSE IS A DERIVATIVE WORK OF THE APACHE LICENSE +VERSION 2.0 (AVAILABLE AT HTTPS://WWW.APACHE.ORG/LICENSES/LICENSE-2.0). IN OTHER +WORDS, THIS LICENSE CONTAINS ADDITIONAL CONDITIONS THAT THE APACHE LICENSE 2.0 +DOES NOT CONTAIN. PLEASE READ THIS LICENSE CAREFULLY, AS IT IS DIFFERENT FROM +OTHER ‘OPEN ACCESS’ LICENSES YOU MAY HAVE ENCOUNTERED PREVIOUSLY. + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the purposes + of this definition, "submitted" means any form of electronic, verbal, or + written communication sent to the Licensor or its representatives, including + but not limited to communication on electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, or on behalf of, + the Licensor for the purpose of discussing and improving the Work, but excluding + communication that is conspicuously marked or otherwise designated in + writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and subsequently + incorporated within the Work. + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial revisions, + annotations, elaborations, or other modifications represent, as a whole, an original + work of authorship. For the purposes of this License, Derivative Works shall + not include works that remain separable from, or merely link (or bind by name) + to the interfaces of, the Work and Derivative Works thereof. + + "Legal Entity" shall mean an organization that has less than one hundred (100) + employees and less than Ten Million U.S. Dollars ($10,000,000.00) in annual revenue. + + "License" shall mean the terms and conditions for use, reproduction, and + distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright + owner that is granting the License. + + "Object" form shall mean any form resulting from mechanical transformation or + translation of a Source form, including but not limited to compiled object code, + generated documentation, and conversions to other media types. + + "Source" form shall mean the preferred form for making modifications, including + but not limited to software source code, documentation source, and configuration files. + + "Work" shall mean the work of authorship, whether in Source or Object form, + made available under the License, as indicated by a copyright notice that is + included in or attached to the work (an example is provided in the Appendix below). + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, + each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the Work and such + Derivative Works in Source or Object form. For clarity, the requirement that the party + exercising this license must be either an individual or a Legal Entity is an express + condition to the grant of the foregoing license. If the conditions of this License are + not met, no grant of license under this Section 2 exists. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, + each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable (except as stated in this section) patent license to make, + have made, use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable by such Contributor + that are necessarily infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a crossclaim or + counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated + within the Work constitutes direct or contributory patent infringement, then any patent + licenses granted to You under this License for that Work shall terminate as of the date + such litigation is filed. For clarity, the requirement that the party exercising this + license must be either an individual or a Legal Entity is an express condition to the + grant of the foregoing license. If the conditions of this License are not met, + no grant of license under this Section 3 exists. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works + thereof in any medium, with or without modifications, and in Source or Object form, + provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, + patent, trademark, and attribution notices from the Source form of the Work, excluding those notices + that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable copy + of the attribution notices contained within such NOTICE file, excluding those + notices that do not pertain to any part of the Derivative Works, in at least + one of the following places: within a NOTICE text file distributed as part + of the Derivative Works; within the Source form or documentation, if provided + along with the Derivative Works; or, within a display generated by the + Derivative Works, if and wherever such third-party notices normally appear. + The contents of the NOTICE file are for informational purposes only and do + not modify the License. You may add Your own attribution notices within + Derivative Works that You distribute, alongside or as an addendum to the + NOTICE text from the Work, provided that such additional attribution notices + cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide + additional or different license terms and conditions for use, reproduction, + or distribution of Your modifications, or for any such Derivative Works as a whole, + provided Your use, reproduction, and distribution of the Work otherwise complies + with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution + intentionally submitted for inclusion in the Work by You to the Licensor shall be under + the terms and conditions of this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify the terms of any + separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the tradenames, trademarks, + service marks, or product names of the Licensor, except as required for reasonable and + customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, + Licensor provides the Work (and each Contributor provides its Contributions) on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, + MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for + determining the appropriateness of using or redistributing the Work and assume any risks + associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort + (including negligence), contract, or otherwise, unless required by applicable law + (such as deliberate and grossly negligent acts) or agreed to in writing, shall any + Contributor be liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a result of this + License or out of the use or inability to use the Work (including but not limited + to damages for loss of goodwill, work stoppage, computer failure or malfunction, + or any and all other commercial damages or losses), even if such Contributor has + been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or + Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance + of support, warranty, indemnity, or other liability obligations and/or rights + consistent with this License. However, in accepting such obligations, You may act + only on Your own behalf and on Your sole responsibility, not on behalf of any other + Contributor, and only if You agree to indemnify, defend, and hold each Contributor + harmless for any liability incurred by, or claims asserted against, such Contributor + by reason of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Teleport Community Edition License to your work. + + To apply the Teleport Community Edition License to your work, + attach the following boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include the brackets!) + The text should be enclosed in the appropriate comment syntax for the file format. + We also recommend that a file or class name and description of purpose be included + on the same "printed page" as the copyright notice for easier identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Teleport Community Edition License, Version 1.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://github.com/gravitational/teleport/blob/master/build.assets/LICENSE-community + + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. \ No newline at end of file diff --git a/src/licensedcode/data/rules/other-permissive_1066.RULE b/src/licensedcode/data/rules/other-permissive_1066.RULE index 1b6aed99984..b69a376b757 100644 --- a/src/licensedcode/data/rules/other-permissive_1066.RULE +++ b/src/licensedcode/data/rules/other-permissive_1066.RULE @@ -1,6 +1,8 @@ --- license_expression: other-permissive is_license_notice: yes +is_deprecated: yes +notes: This is now the socketxx-2003.LICENSE --- // Permission is granted to use at your own risk and distribute this software From a534fcf6b908c81b51fd2f08285fc18069114dba Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 14 Jan 2025 03:26:12 +0530 Subject: [PATCH 25/29] Update package assembly in conda installations Parse conda metadata JSON manifests and use the package data and files information present to improve conda package assembly. Reference: https://github.com/aboutcode-org/scancode-toolkit/issues/4083 Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/__init__.py | 1 + src/packagedcode/conda.py | 269 ++++++- .../data/conda/assembly-conda-scan.json | 677 ++++++++++++++++++ .../requests-2.32.3-py312h06a4308_1.json | 45 ++ .../requests-2.32.3.dist-info/LICENSE | 1 + .../requests-2.32.3.dist-info/METADATA | 18 + .../site-packages/requests/__init__.py | 1 + .../info/recipe/meta.yaml | 57 ++ .../site-packages/requests/__init__.py | 1 + .../conda-meta/tzdata-2024b-h04d1e81_0.json | 36 + .../conda/conda-meta/tzdata-expected.json | 79 ++ .../meta-yaml/pippy/meta.yaml-scancode.json | 4 +- tests/packagedcode/test_conda.py | 51 ++ 13 files changed, 1237 insertions(+), 3 deletions(-) create mode 100644 tests/packagedcode/data/conda/assembly-conda-scan.json create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests/__init__.py create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml create mode 100644 tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests/__init__.py create mode 100644 tests/packagedcode/data/conda/conda-meta/tzdata-2024b-h04d1e81_0.json create mode 100644 tests/packagedcode/data/conda/conda-meta/tzdata-expected.json diff --git a/src/packagedcode/__init__.py b/src/packagedcode/__init__.py index 778d0434922..9cc46d0e09b 100644 --- a/src/packagedcode/__init__.py +++ b/src/packagedcode/__init__.py @@ -73,6 +73,7 @@ cocoapods.PodfileLockHandler, cocoapods.PodfileHandler, + conda.CondaMetaJsonHandler, conda.CondaMetaYamlHandler, conda.CondaYamlHandler, diff --git a/src/packagedcode/conda.py b/src/packagedcode/conda.py index 80b71cbb12b..d2155530688 100644 --- a/src/packagedcode/conda.py +++ b/src/packagedcode/conda.py @@ -8,6 +8,7 @@ # import io +import json import saneyaml from packageurl import PackageURL @@ -23,7 +24,267 @@ See https://repo.continuum.io/pkgs/free for examples. """ -# TODO: there are likely other package data files for Conda + +class CondaBaseHandler(models.DatafileHandler): + """ + Assemble package data and files present in conda manifests present in the + usual structure of a conda installation. Here the manifests which are + assembled together are: + - Conda metadata JSON (CondaMetaJsonHandler) + - Conda meta.yaml recipe (CondaMetaYamlHandler) + + Example paths for these manifests: + /opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json + /opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml + """ + + @classmethod + def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_package): + + if codebase.has_single_resource: + yield from models.DatafileHandler.assemble(package_data, resource, codebase, package_adder) + return + + # We do not have any package data detected here + if not resource.package_data: + return + + # If this is a Conda meta.yaml, try to find the corresponding metadata JSON + # and if present, run assembly on the metadata resource + if CondaMetaYamlHandler.is_datafile(resource.location): + conda_meta_json = cls.find_conda_meta_json_resource(resource, codebase) + if conda_meta_json: + package_data_meta_json, = conda_meta_json.package_data + yield from cls.assemble( + package_data=package_data_meta_json, + resource=conda_meta_json, + codebase=codebase, + package_adder=package_adder, + ) + + # corresponding metadata JSON does not exist, so handle this meta.yaml + elif package_data.purl: + package = models.Package.from_package_data( + package_data=package_data, + datafile_path=resource.path, + ) + package.populate_license_fields() + yield package + + CondaMetaYamlHandler.assign_package_to_resources( + package=package, + resource=resource, + codebase=codebase, + package_adder=package_adder, + ) + yield resource + + return + + # For a conda metadata JSON, try to find the corresponding meta.yaml and + # assemble a single package out of these if it exists + conda_meta_yaml = cls.find_conda_meta_yaml_resource(resource, codebase) + if not package_data.purl: + yield resource + return + + package = models.Package.from_package_data( + package_data=package_data, + datafile_path=resource.path, + ) + if conda_meta_yaml: + conda_meta_yaml_package_data, = conda_meta_yaml.package_data + package.update( + package_data=conda_meta_yaml_package_data, + datafile_path=conda_meta_yaml.path, + ) + cls.assign_package_to_resources( + package=package, + resource=conda_meta_yaml, + codebase=codebase, + package_adder=package_adder, + ) + yield conda_meta_yaml + + package.populate_license_fields() + yield package + + cls.assign_package_to_resources( + package=package, + resource=resource, + codebase=codebase, + package_adder=package_adder, + ) + + # we yield this as we do not want this further processed + yield resource + + # Get the file paths present in the metadata JSON and assign them to + # the package created from it + extracted_package_dir = package_data.extra_data.get('extracted_package_dir') + files = package_data.extra_data.get('files') + + if not extracted_package_dir or not files: + return + + conda_metadata_dir = resource.parent(codebase) + if not conda_metadata_dir: + return + + conda_root_dir = conda_metadata_dir.parent(codebase) + if not conda_root_dir: + return + + root_path_segment, _, package_dir = extracted_package_dir.rpartition("/pkgs/") + if not conda_root_dir.path.endswith(root_path_segment): + return + + package_dir_path = f"{conda_root_dir.path}/pkgs/{package_dir}" + package_dir_resource = codebase.get_resource(path=package_dir_path) + if package_dir_resource: + cls.assign_package_to_resources( + package=package, + resource=package_dir_resource, + codebase=codebase, + package_adder=package_adder, + ) + + conda_package_path = f"{conda_root_dir.path}/pkgs/{package_dir}.conda" + conda_package_resource = codebase.get_resource(path=conda_package_path) + if conda_package_resource: + cls.assign_package_to_resources( + package=package, + resource=conda_package_resource, + codebase=codebase, + package_adder=package_adder, + ) + + for file_path in files: + full_file_path = f"{conda_root_dir.path}/{file_path}" + file_resource = codebase.get_resource(path=full_file_path) + if file_resource: + cls.assign_package_to_resources( + package=package, + resource=file_resource, + codebase=codebase, + package_adder=package_adder, + ) + + @classmethod + def check_valid_packages_dir_name(cls, package_dir_resource, resource, codebase): + """ + Return the name of the `package_dir_resource`, if it is valid, i.e. + the package (name, version) data present in `resource` matches the + directory name, and the package directory is present in it's usual + location in a conda installation. + """ + package_dir_parent = package_dir_resource.parent(codebase) + + meta_yaml_package_data, = resource.package_data + name = meta_yaml_package_data.get("name") + version = meta_yaml_package_data.get("version") + if f"{name}-{version}" in package_dir_resource.name and ( + package_dir_parent and "pkgs" in package_dir_parent.name + ): + return package_dir_resource.name + + @classmethod + def find_conda_meta_json_resource(cls, resource, codebase): + """ + Given a resource for a conda meta.yaml resource, find if it has any + corresponding metadata JSON located inside the conda-meta/ directory, + and return the resource if they exist, else return None. + """ + package_dir_resource = CondaMetaYamlHandler.get_conda_root(resource, codebase) + if not package_dir_resource or not resource.package_data: + return + + package_dir_name = cls.check_valid_packages_dir_name( + package_dir_resource=package_dir_resource, + resource=resource, + codebase=codebase, + ) + if not package_dir_name: + return + + root_resource = package_dir_resource.parent(codebase).parent(codebase) + if not root_resource: + return + + root_resource_path = root_resource.path + conda_meta_path = f"{root_resource_path}/conda-meta/{package_dir_name}.json" + conda_meta_resource = codebase.get_resource(path=conda_meta_path) + + if conda_meta_resource and conda_meta_resource.package_data: + return conda_meta_resource + + @classmethod + def find_conda_meta_yaml_resource(cls, resource, codebase): + """ + Given a resource for a metadata JSON located inside the conda-meta/ + directory, find if it has any corresponding conda meta.yaml, and return + the resource if they exist, else return None. + """ + package_dir_name, _json, _ = resource.name.rpartition(".json") + parent_resource = resource.parent(codebase) + if not parent_resource and not parent_resource.name == "conda-meta": + return + + root_resource = parent_resource.parent(codebase) + if not root_resource: + return + + root_resource_path = root_resource.path + package_dir_path = f"{root_resource_path}/pkgs/{package_dir_name}/" + package_dir_resource = codebase.get_resource(path=package_dir_path) + if not package_dir_resource: + return + + meta_yaml_path = f"{package_dir_path}info/recipe/meta.yaml" + meta_yaml_resource = codebase.get_resource(path=meta_yaml_path) + if meta_yaml_resource and meta_yaml_resource.package_data: + return meta_yaml_resource + + +class CondaMetaJsonHandler(CondaBaseHandler): + datasource_id = 'conda_meta_json' + path_patterns = ('*conda-meta/*.json',) + default_package_type = 'conda' + default_primary_language = 'Python' + description = 'Conda metadata JSON in rootfs' + documentation_url = 'https://docs.conda.io/' + + @classmethod + def parse(cls, location, package_only=False): + with io.open(location, encoding='utf-8') as loc: + conda_metadata = json.load(loc) + + name = conda_metadata.get('name') + version = conda_metadata.get('version') + extracted_license_statement = conda_metadata.get('license') + download_url = conda_metadata.get('url') + + extra_data_fields = ['requested_spec', 'channel'] + package_file_fields = ['extracted_package_dir', 'files', 'package_tarball_full_path'] + other_package_fields = ['size', 'md5', 'sha256'] + + extra_data = {} + for metadata_field in extra_data_fields + package_file_fields: + extra_data[metadata_field] = conda_metadata.get(metadata_field) + + package_data = dict( + datasource_id=cls.datasource_id, + type=cls.default_package_type, + name=name, + version=version, + extracted_license_statement=extracted_license_statement, + download_url=download_url, + extra_data=extra_data, + ) + for package_field in other_package_fields: + package_data[package_field] = conda_metadata.get(package_field) + yield models.PackageData.from_data(package_data, package_only) + class CondaYamlHandler(BaseDependencyFileHandler): datasource_id = 'conda_yaml' @@ -55,7 +316,7 @@ def parse(cls, location, package_only=False): yield models.PackageData.from_data(package_data, package_only) -class CondaMetaYamlHandler(models.DatafileHandler): +class CondaMetaYamlHandler(CondaBaseHandler): datasource_id = 'conda_meta_yaml' default_package_type = 'conda' path_patterns = ('*/meta.yaml',) @@ -67,6 +328,9 @@ def get_conda_root(cls, resource, codebase): """ Return a root Resource given a meta.yaml ``resource``. """ + if not resource: + return + # the root is either the parent or further up for yaml stored under # an "info" dir. We support extractcode extraction. # in a source repo it would be in /conda.recipe/meta.yaml @@ -74,6 +338,7 @@ def get_conda_root(cls, resource, codebase): 'info/recipe.tar-extract/recipe/meta.yaml', 'info/recipe/recipe/meta.yaml', 'conda.recipe/meta.yaml', + 'info/recipe/meta.yaml', ) res = resource for pth in paths: diff --git a/tests/packagedcode/data/conda/assembly-conda-scan.json b/tests/packagedcode/data/conda/assembly-conda-scan.json new file mode 100644 index 00000000000..cff1b74e492 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly-conda-scan.json @@ -0,0 +1,677 @@ +{ + "packages": [ + { + "type": "conda", + "namespace": null, + "name": "requests", + "version": "2.32.3", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": "Requests is an elegant and simple HTTP library for Python, built with \u2665.", + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://requests.readthedocs.io/", + "download_url": "https://repo.anaconda.com/pkgs/main/linux-64/requests-2.32.3-py312h06a4308_1.conda", + "size": 125693, + "sha1": null, + "md5": "8cc2fc3e2198c2efe6cd890a7684a16a", + "sha256": "940b9ae3f0b64e7ee51dfbdcfcffc674a447e5592f8a66d8064cd505fc122b78", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": "https://github.com/psf/requests", + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + }, + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "Apache-2.0", + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "requested_spec": "defaults/linux-64::requests==2.32.3=py312h06a4308_1[md5=8cc2fc3e2198c2efe6cd890a7684a16a]", + "channel": "https://repo.anaconda.com/pkgs/main/linux-64", + "extracted_package_dir": "/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1", + "files": [ + "lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE", + "lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "lib/python3.12/site-packages/requests/__init__.py" + ], + "package_tarball_full_path": "opt/conda/pkgs/requests-2.32.3-py312h06a4308_1.conda" + }, + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "package_uid": "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json", + "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml" + ], + "datasource_ids": [ + "conda_meta_json", + "conda_meta_yaml" + ], + "purl": "pkg:conda/requests@2.32.3" + }, + { + "type": "pypi", + "namespace": null, + "name": "requests", + "version": "2.32.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Python HTTP for Humans.", + "release_date": null, + "parties": [ + { + "type": "person", + "role": "author", + "name": "Kenneth Reitz", + "email": "me@kennethreitz.org", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3" + ], + "homepage_url": "https://requests.readthedocs.io", + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": "https://github.com/psf/requests", + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "license: Apache-2.0\n", + "notice_text": null, + "source_packages": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "Documentation": "https://requests.readthedocs.io" + }, + "repository_homepage_url": "https://pypi.org/project/requests", + "repository_download_url": "https://pypi.org/packages/source/r/requests/requests-2.32.3.tar.gz", + "api_data_url": "https://pypi.org/pypi/requests/2.32.3/json", + "package_uid": "pkg:pypi/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_paths": [ + "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA" + ], + "datasource_ids": [ + "pypi_wheel_metadata" + ], + "purl": "pkg:pypi/requests@2.32.3" + } + ], + "dependencies": [ + { + "purl": "pkg:pypi/charset-normalizer", + "extracted_requirement": "<4,>=2", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:pypi/charset-normalizer?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:pypi/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "datasource_id": "pypi_wheel_metadata" + } + ], + "files": [ + { + "path": "assembly", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/conda-meta", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json", + "type": "file", + "package_data": [ + { + "type": "conda", + "namespace": null, + "name": "requests", + "version": "2.32.3", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": "https://repo.anaconda.com/pkgs/main/linux-64/requests-2.32.3-py312h06a4308_1.conda", + "size": 125693, + "sha1": null, + "md5": "8cc2fc3e2198c2efe6cd890a7684a16a", + "sha256": "940b9ae3f0b64e7ee51dfbdcfcffc674a447e5592f8a66d8064cd505fc122b78", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "Apache-2.0", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "requested_spec": "defaults/linux-64::requests==2.32.3=py312h06a4308_1[md5=8cc2fc3e2198c2efe6cd890a7684a16a]", + "channel": "https://repo.anaconda.com/pkgs/main/linux-64", + "extracted_package_dir": "/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1", + "files": [ + "lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE", + "lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "lib/python3.12/site-packages/requests/__init__.py" + ], + "package_tarball_full_path": "opt/conda/pkgs/requests-2.32.3-py312h06a4308_1.conda" + }, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_json", + "purl": "pkg:conda/requests@2.32.3" + } + ], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages/requests", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE", + "type": "file", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "type": "file", + "package_data": [ + { + "type": "pypi", + "namespace": null, + "name": "requests", + "version": "2.32.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Python HTTP for Humans.", + "release_date": null, + "parties": [ + { + "type": "person", + "role": "author", + "name": "Kenneth Reitz", + "email": "me@kennethreitz.org", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3" + ], + "homepage_url": "https://requests.readthedocs.io", + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": "https://github.com/psf/requests", + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "license: Apache-2.0\n", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "Documentation": "https://requests.readthedocs.io" + }, + "dependencies": [ + { + "purl": "pkg:pypi/charset-normalizer", + "extracted_requirement": "<4,>=2", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://pypi.org/project/requests", + "repository_download_url": "https://pypi.org/packages/source/r/requests/requests-2.32.3.tar.gz", + "api_data_url": "https://pypi.org/pypi/requests/2.32.3/json", + "datasource_id": "pypi_wheel_metadata", + "purl": "pkg:pypi/requests@2.32.3" + } + ], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "pkg:pypi/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/lib/python3.12/site-packages/requests/__init__.py", + "type": "file", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs", + "type": "directory", + "package_data": [], + "for_packages": [], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "type": "file", + "package_data": [ + { + "type": "conda", + "namespace": null, + "name": "requests", + "version": "2.32.3", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": "Requests is an elegant and simple HTTP library for Python, built with \u2665.", + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://requests.readthedocs.io/", + "download_url": "https://pypi.io/packages/source/r/requests/requests-2.32.3.tar.gz", + "size": null, + "sha1": null, + "md5": null, + "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": "https://github.com/psf/requests", + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0", + "declared_license_expression_spdx": "Apache-2.0", + "license_detections": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "matches": [ + { + "license_expression": "apache-2.0", + "license_expression_spdx": "Apache-2.0", + "from_file": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 3, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/spdx_license_id_apache-2.0_for_apache-2.0.RULE", + "matched_text": "Apache-2.0" + } + ], + "identifier": "apache_2_0-d66ab77d-a5cc-7104-e702-dc7df61fe9e8" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "Apache-2.0", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:conda/zlib", + "extracted_requirement": "1.2.13 h5eee18b_1", + "scope": "host", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/certifi", + "extracted_requirement": ">=2017.4.17", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:conda/chardet", + "extracted_requirement": ">=3.0.2,<6", + "scope": "run_constrained", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_yaml", + "purl": "pkg:conda/requests@2.32.3" + } + ], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests", + "type": "directory", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + }, + { + "path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests/__init__.py", + "type": "file", + "package_data": [], + "for_packages": [ + "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758" + ], + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json b/tests/packagedcode/data/conda/assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json new file mode 100644 index 00000000000..085fad49dd6 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/conda-meta/requests-2.32.3-py312h06a4308_1.json @@ -0,0 +1,45 @@ +{ + "arch": "x86_64", + "build": "py312h06a4308_1", + "build_number": 1, + "channel": "https://repo.anaconda.com/pkgs/main/linux-64", + "constrains": [ + "pysocks >=1.5.6,!=1.5.7", + "chardet >=3.0.2,<6" + ], + "depends": [ + "certifi >=2017.4.17", + "charset-normalizer >=2,<4", + "idna >=2.5,<4", + "python >=3.12,<3.13.0a0", + "urllib3 >=1.21.1,<3" + ], + "extracted_package_dir": "/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1", + "files": [ + "lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE", + "lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA", + "lib/python3.12/site-packages/requests/__init__.py" + ], + "fn": "requests-2.32.3-py312h06a4308_1.conda", + "license": "Apache-2.0", + "license_family": "Apache", + "link": { + "source": "opt/conda/pkgs/requests-2.32.3-py312h06a4308_1", + "type": 1 + }, + "md5": "8cc2fc3e2198c2efe6cd890a7684a16a", + "name": "requests", + "package_tarball_full_path": "opt/conda/pkgs/requests-2.32.3-py312h06a4308_1.conda", + "paths_data": { + "paths": [], + "paths_version": 1 + }, + "platform": "linux", + "requested_spec": "defaults/linux-64::requests==2.32.3=py312h06a4308_1[md5=8cc2fc3e2198c2efe6cd890a7684a16a]", + "sha256": "940b9ae3f0b64e7ee51dfbdcfcffc674a447e5592f8a66d8064cd505fc122b78", + "size": 125693, + "subdir": "linux-64", + "timestamp": 1730999176000, + "url": "https://repo.anaconda.com/pkgs/main/linux-64/requests-2.32.3-py312h06a4308_1.conda", + "version": "2.32.3" +} \ No newline at end of file diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE new file mode 100644 index 00000000000..2e85972ece4 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE @@ -0,0 +1 @@ +Apache License Version 2.0 \ No newline at end of file diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA new file mode 100644 index 00000000000..1166fc320a1 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA @@ -0,0 +1,18 @@ +Metadata-Version: 2.1 +Name: requests +Version: 2.32.3 +Summary: Python HTTP for Humans. +Home-page: https://requests.readthedocs.io +Author: Kenneth Reitz +Author-email: me@kennethreitz.org +License: Apache-2.0 +Project-URL: Documentation, https://requests.readthedocs.io +Project-URL: Source, https://github.com/psf/requests +Classifier: Development Status :: 5 - Production/Stable +Classifier: Natural Language :: English +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: charset-normalizer<4,>=2 diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests/__init__.py b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/lib/python3.12/site-packages/requests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml b/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml new file mode 100644 index 00000000000..7615c560abe --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml @@ -0,0 +1,57 @@ +# This file created by conda-build 24.1.2 +# meta.yaml template originally from: +# /feedstock/recipe, last modified Thu Nov 7 17:05:12 2024 +# ------------------------------------------------ + +package: + name: requests + version: 2.32.3 +source: + sha256: 55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 + url: https://pypi.io/packages/source/r/requests/requests-2.32.3.tar.gz +requirements: + host: + - zlib 1.2.13 h5eee18b_1 + run: + - certifi >=2017.4.17 + run_constrained: + - chardet >=3.0.2,<6 +test: + commands: + - pip check + - conda create -v --dry-run -n requests-test numpy + imports: + - requests + requires: + - conda + - pip +about: + description: 'Requests is the only Non-GMO HTTP library for Python, safe for human + + consumption. + + ' + dev_url: https://github.com/psf/requests + doc_url: https://requests.readthedocs.io/ + home: https://requests.readthedocs.io/ + license: Apache-2.0 + license_family: Apache + license_file: LICENSE + summary: "Requests is an elegant and simple HTTP library for Python, built with\ + \ \u2665." +extra: + copy_test_source_files: true + final: true + flow_run_id: a6780417-397a-4b4b-9b26-7ad861f84324 + recipe-maintainers: + - carlodri + - jakirkham + - kalefranz + - mcg1969 + - mingwandroid + - msarahan + - ocefpaf + - pelson + - sigmavirus24 + remote_url: git@github.com:AnacondaRecipes/requests-feedstock.git + sha: 997bb0da1a210a5aeef4073b32f674eaf1f8eaca \ No newline at end of file diff --git a/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests/__init__.py b/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/packagedcode/data/conda/assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/lib/python3.12/site-packages/requests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/packagedcode/data/conda/conda-meta/tzdata-2024b-h04d1e81_0.json b/tests/packagedcode/data/conda/conda-meta/tzdata-2024b-h04d1e81_0.json new file mode 100644 index 00000000000..bae5927378b --- /dev/null +++ b/tests/packagedcode/data/conda/conda-meta/tzdata-2024b-h04d1e81_0.json @@ -0,0 +1,36 @@ +{ + "build": "h04d1e81_0", + "build_number": 0, + "channel": "https://repo.anaconda.com/pkgs/main/noarch", + "constrains": [], + "depends": [], + "extracted_package_dir": "/opt/conda/pkgs/tzdata-2024b-h04d1e81_0", + "files": [ + "share/zoneinfo/Asia/Kolkata", + "share/zoneinfo/tzdata.zi", + "share/zoneinfo/zone.tab" + ], + "fn": "tzdata-2024b-h04d1e81_0.conda", + "license": "CC-PDDC OR BSD-3-Clause", + "license_family": "BSD", + "link": { + "source": "/opt/conda/pkgs/tzdata-2024b-h04d1e81_0", + "type": 1 + }, + "md5": "9be694715c6a65f9631bb1b242125e9d", + "name": "tzdata", + "noarch": "generic", + "package_tarball_full_path": "/opt/conda/pkgs/tzdata-2024b-h04d1e81_0.conda", + "package_type": "noarch_generic", + "paths_data": { + "paths": [], + "paths_version": 1 + }, + "requested_spec": "defaults/noarch::tzdata==2024b=h04d1e81_0[md5=9be694715c6a65f9631bb1b242125e9d]", + "sha256": "9fdd287b55be4c475789a69d3b94cdb73f756583a6d7306da1706e43eee573da", + "size": 117432, + "subdir": "noarch", + "timestamp": 1728062827000, + "url": "https://repo.anaconda.com/pkgs/main/noarch/tzdata-2024b-h04d1e81_0.conda", + "version": "2024b" +} \ No newline at end of file diff --git a/tests/packagedcode/data/conda/conda-meta/tzdata-expected.json b/tests/packagedcode/data/conda/conda-meta/tzdata-expected.json new file mode 100644 index 00000000000..84141ae2dab --- /dev/null +++ b/tests/packagedcode/data/conda/conda-meta/tzdata-expected.json @@ -0,0 +1,79 @@ +[ + { + "type": "conda", + "namespace": null, + "name": "tzdata", + "version": "2024b", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": "https://repo.anaconda.com/pkgs/main/noarch/tzdata-2024b-h04d1e81_0.conda", + "size": 117432, + "sha1": null, + "md5": "9be694715c6a65f9631bb1b242125e9d", + "sha256": "9fdd287b55be4c475789a69d3b94cdb73f756583a6d7306da1706e43eee573da", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "cc-pd OR bsd-new", + "declared_license_expression_spdx": "CC-PDDC OR BSD-3-Clause", + "license_detections": [ + { + "license_expression": "cc-pd OR bsd-new", + "license_expression_spdx": "CC-PDDC OR BSD-3-Clause", + "matches": [ + { + "license_expression": "cc-pd OR bsd-new", + "license_expression_spdx": "CC-PDDC OR BSD-3-Clause", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 6, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-cc_pd_or_bsd_new-7ed06e8faddcea41dbd5ba6b6a1103da7451d4c1", + "rule_url": null, + "matched_text": "CC-PDDC OR BSD-3-Clause" + } + ], + "identifier": "cc_pd_or_bsd_new-59c31305-cd29-a988-bea8-38f97ce1950f" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "CC-PDDC OR BSD-3-Clause", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "requested_spec": "defaults/noarch::tzdata==2024b=h04d1e81_0[md5=9be694715c6a65f9631bb1b242125e9d]", + "channel": "https://repo.anaconda.com/pkgs/main/noarch", + "extracted_package_dir": "/opt/conda/pkgs/tzdata-2024b-h04d1e81_0", + "files": [ + "share/zoneinfo/Asia/Kolkata", + "share/zoneinfo/tzdata.zi", + "share/zoneinfo/zone.tab" + ], + "package_tarball_full_path": "/opt/conda/pkgs/tzdata-2024b-h04d1e81_0.conda" + }, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "conda_meta_json", + "purl": "pkg:conda/tzdata@2024b" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json index d41b17c4418..d55dac7f9a7 100644 --- a/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json +++ b/tests/packagedcode/data/conda/meta-yaml/pippy/meta.yaml-scancode.json @@ -376,7 +376,9 @@ "purl": "pkg:conda/pippy@0.1.0" } ], - "for_packages": [], + "for_packages": [ + "pkg:conda/pippy@0.1.0?uuid=fixed-uid-done-for-testing-5642512d1758" + ], "scan_errors": [] } ] diff --git a/tests/packagedcode/test_conda.py b/tests/packagedcode/test_conda.py index 05df09149a6..4753beefef5 100644 --- a/tests/packagedcode/test_conda.py +++ b/tests/packagedcode/test_conda.py @@ -7,6 +7,7 @@ # See https://aboutcode.org for more information about nexB OSS projects. # +import attr import os from commoncode.resource import Codebase @@ -113,3 +114,53 @@ def test_parse_conda_yaml_simple_dependencies(self): package = conda.CondaYamlHandler.parse(test_file) expected_loc = self.get_test_loc('conda/conda-yaml/ringer/environment.yaml-expected.json') self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_conda_get_conda_meta_json(self): + meta_yaml_path = 'conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml' + conda_meta_json_path = 'conda/conda-meta/requests-2.32.3-py312h06a4308_1.json' + + test_dir = self.get_test_loc('conda/assembly/opt/conda/') + resource_attributes = dict(package_data=attr.ib(default=attr.Factory(list), repr=False),) + codebase = Codebase(location=test_dir, resource_attributes=resource_attributes) + + package_data = [{'name': 'requests', 'version':'2.32.3'}] + meta_yaml_resource = codebase.get_resource(path=meta_yaml_path) + setattr(meta_yaml_resource, 'package_data', package_data) + codebase.save_resource(meta_yaml_resource) + conda_meta_json_resource = codebase.get_resource(path=conda_meta_json_path) + setattr(conda_meta_json_resource, 'package_data', package_data) + codebase.save_resource(conda_meta_json_resource) + + meta_json = conda.CondaBaseHandler.find_conda_meta_json_resource(meta_yaml_resource, codebase) + assert meta_json.path == conda_meta_json_path + + meta_yaml = conda.CondaBaseHandler.find_conda_meta_yaml_resource(conda_meta_json_resource, codebase) + assert meta_yaml.path == meta_yaml_path + + def test_conda_pkgs_meta_yaml_root_dir(self): + meta_yaml_path = 'conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml' + root_path = 'conda/pkgs/requests-2.32.3-py312h06a4308_1' + test_dir = self.get_test_loc('conda/assembly/opt/conda/') + codebase = Codebase(test_dir) + resource = codebase.get_resource(path=meta_yaml_path) + proot = conda.CondaMetaYamlHandler.get_conda_root(resource, codebase) + assert proot.path == root_path + + def test_parse_is_datafile_conda_meta_package_with_files(self): + test_file = self.get_test_loc('conda/conda-meta/tzdata-2024b-h04d1e81_0.json') + assert conda.CondaMetaJsonHandler.is_datafile(test_file) + + def test_parse_conda_meta_package_with_files(self): + test_file = self.get_test_loc('conda/conda-meta/tzdata-2024b-h04d1e81_0.json') + package = conda.CondaMetaJsonHandler.parse(test_file) + expected_loc = self.get_test_loc('conda/conda-meta/tzdata-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_conda_meta_yaml_conda_meta_assemble_from_rootfs(self): + test_location = self.get_test_loc('conda/assembly/') + result_file = self.get_temp_file('results.json') + run_scan_click(['--package', test_location, '--json', result_file]) + expected_file = self.get_test_loc('conda/assembly-conda-scan.json') + check_json_scan( + expected_file, result_file, remove_uuid=True, regen=REGEN_TEST_FIXTURES + ) From dce5b2a455eaa55bb6e493b48647403bf49f9d43 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 14 Jan 2025 03:39:47 +0530 Subject: [PATCH 26/29] Replace deprecated macos-12 runner with macos-14 Signed-off-by: Ayan Sinha Mahapatra --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 28389ccc9e7..7f3f89f6e4f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -233,8 +233,8 @@ jobs: - template: etc/ci/azure-posix.yml parameters: - job_name: macos12_cpython_latest_from_pip - image_name: macos-12 + job_name: macos14_cpython_latest_from_pip + image_name: macos-14 python_versions: ['3.9', '3.10', '3.11', '3.12'] test_suites: all: venv/bin/pip install --upgrade-strategy eager --force-reinstall --upgrade -e .[testing] && venv/bin/pytest -n 2 -vvs tests/scancode/test_cli.py From 20663f45f0cc0743e179117c28914387598e177b Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 14 Jan 2025 15:16:58 +0530 Subject: [PATCH 27/29] Report top level dependencies properly for conda packages Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/conda.py | 17 +++++++ .../data/conda/assembly-conda-scan.json | 45 +++++++++++++++++++ .../data/plugin/plugins_list_linux.txt | 7 +++ 3 files changed, 69 insertions(+) diff --git a/src/packagedcode/conda.py b/src/packagedcode/conda.py index d2155530688..855d4a10039 100644 --- a/src/packagedcode/conda.py +++ b/src/packagedcode/conda.py @@ -71,6 +71,15 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ package.populate_license_fields() yield package + dependent_packages = package_data.dependencies + if dependent_packages: + yield from models.Dependency.from_dependent_packages( + dependent_packages=dependent_packages, + datafile_path=resource.path, + datasource_id=package_data.datasource_id, + package_uid=package.package_uid, + ) + CondaMetaYamlHandler.assign_package_to_resources( package=package, resource=resource, @@ -104,6 +113,14 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ codebase=codebase, package_adder=package_adder, ) + meta_yaml_package_data = models.PackageData.from_dict(conda_meta_yaml_package_data) + if meta_yaml_package_data.dependencies: + yield from models.Dependency.from_dependent_packages( + dependent_packages=meta_yaml_package_data.dependencies, + datafile_path=conda_meta_yaml.path, + datasource_id=meta_yaml_package_data.datasource_id, + package_uid=package.package_uid, + ) yield conda_meta_yaml package.populate_license_fields() diff --git a/tests/packagedcode/data/conda/assembly-conda-scan.json b/tests/packagedcode/data/conda/assembly-conda-scan.json index cff1b74e492..97cecaa7c8f 100644 --- a/tests/packagedcode/data/conda/assembly-conda-scan.json +++ b/tests/packagedcode/data/conda/assembly-conda-scan.json @@ -193,6 +193,51 @@ } ], "dependencies": [ + { + "purl": "pkg:conda/zlib", + "extracted_requirement": "1.2.13 h5eee18b_1", + "scope": "host", + "is_runtime": false, + "is_optional": true, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/zlib?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/certifi", + "extracted_requirement": ">=2017.4.17", + "scope": "run", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/certifi?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "datasource_id": "conda_meta_yaml" + }, + { + "purl": "pkg:conda/chardet", + "extracted_requirement": ">=3.0.2,<6", + "scope": "run_constrained", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {}, + "dependency_uid": "pkg:conda/chardet?uuid=fixed-uid-done-for-testing-5642512d1758", + "for_package_uid": "pkg:conda/requests@2.32.3?uuid=fixed-uid-done-for-testing-5642512d1758", + "datafile_path": "assembly/opt/conda/pkgs/requests-2.32.3-py312h06a4308_1/info/recipe/meta.yaml", + "datasource_id": "conda_meta_yaml" + }, { "purl": "pkg:pypi/charset-normalizer", "extracted_requirement": "<4,>=2", diff --git a/tests/packagedcode/data/plugin/plugins_list_linux.txt b/tests/packagedcode/data/plugin/plugins_list_linux.txt index 33886e87222..e24512dfd91 100755 --- a/tests/packagedcode/data/plugin/plugins_list_linux.txt +++ b/tests/packagedcode/data/plugin/plugins_list_linux.txt @@ -195,6 +195,13 @@ Package type: conan description: conan recipe path_patterns: '*/conanfile.py' -------------------------------------------- +Package type: conda + datasource_id: conda_meta_json + documentation URL: https://docs.conda.io/ + primary language: Python + description: Conda metadata JSON in rootfs + path_patterns: '*conda-meta/*.json' +-------------------------------------------- Package type: conda datasource_id: conda_meta_yaml documentation URL: https://docs.conda.io/ From 32f8797f097d96521dbcc801c0e84ecf18f508a1 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 14 Jan 2025 19:20:28 +0530 Subject: [PATCH 28/29] Refactor conda package assembly Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/conda.py | 141 +++++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 46 deletions(-) diff --git a/src/packagedcode/conda.py b/src/packagedcode/conda.py index 855d4a10039..29bee04eac3 100644 --- a/src/packagedcode/conda.py +++ b/src/packagedcode/conda.py @@ -63,36 +63,16 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ ) # corresponding metadata JSON does not exist, so handle this meta.yaml - elif package_data.purl: - package = models.Package.from_package_data( + else: + yield from cls.assemble_from_meta_yaml_only( package_data=package_data, - datafile_path=resource.path, - ) - package.populate_license_fields() - yield package - - dependent_packages = package_data.dependencies - if dependent_packages: - yield from models.Dependency.from_dependent_packages( - dependent_packages=dependent_packages, - datafile_path=resource.path, - datasource_id=package_data.datasource_id, - package_uid=package.package_uid, - ) - - CondaMetaYamlHandler.assign_package_to_resources( - package=package, resource=resource, codebase=codebase, package_adder=package_adder, ) - yield resource return - # For a conda metadata JSON, try to find the corresponding meta.yaml and - # assemble a single package out of these if it exists - conda_meta_yaml = cls.find_conda_meta_yaml_resource(resource, codebase) if not package_data.purl: yield resource return @@ -101,27 +81,12 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ package_data=package_data, datafile_path=resource.path, ) - if conda_meta_yaml: - conda_meta_yaml_package_data, = conda_meta_yaml.package_data - package.update( - package_data=conda_meta_yaml_package_data, - datafile_path=conda_meta_yaml.path, - ) - cls.assign_package_to_resources( - package=package, - resource=conda_meta_yaml, - codebase=codebase, - package_adder=package_adder, - ) - meta_yaml_package_data = models.PackageData.from_dict(conda_meta_yaml_package_data) - if meta_yaml_package_data.dependencies: - yield from models.Dependency.from_dependent_packages( - dependent_packages=meta_yaml_package_data.dependencies, - datafile_path=conda_meta_yaml.path, - datasource_id=meta_yaml_package_data.datasource_id, - package_uid=package.package_uid, - ) - yield conda_meta_yaml + yield from cls.get_and_assmeble_from_meta_yaml( + package=package, + resource=resource, + codebase=codebase, + package_adder=package_adder, + ) package.populate_license_fields() yield package @@ -136,8 +101,27 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ # we yield this as we do not want this further processed yield resource - # Get the file paths present in the metadata JSON and assign them to - # the package created from it + cls.assign_packages_to_resources_from_metadata_json( + package=package, + package_data=package_data, + resource=resource, + codebase=codebase, + package_adder=package_adder, + ) + + @classmethod + def assign_packages_to_resources_from_metadata_json( + cls, + package, + package_data, + resource, + codebase, + package_adder=models.add_to_package, + ): + """ + Get the file paths present in the `package_data` of a metadata JSON `resource` + and assign them to the `package` created from the manifest. + """ extracted_package_dir = package_data.extra_data.get('extracted_package_dir') files = package_data.extra_data.get('files') @@ -175,7 +159,7 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ codebase=codebase, package_adder=package_adder, ) - + for file_path in files: full_file_path = f"{conda_root_dir.path}/{file_path}" file_resource = codebase.get_resource(path=full_file_path) @@ -187,6 +171,71 @@ def assemble(cls, package_data, resource, codebase, package_adder=models.add_to_ package_adder=package_adder, ) + @classmethod + def get_and_assmeble_from_meta_yaml(cls, package, resource, codebase, package_adder=models.add_to_package): + """ + For a conda metadata JSON `resource`, try to find the corresponding meta.yaml and + update the `package` from it. Also yield dependencies present in the meta.yaml, + and the `resource` to complete assembling from this manifest. + """ + conda_meta_yaml = cls.find_conda_meta_yaml_resource(resource, codebase) + + if conda_meta_yaml: + conda_meta_yaml_package_data, = conda_meta_yaml.package_data + package.update( + package_data=conda_meta_yaml_package_data, + datafile_path=conda_meta_yaml.path, + ) + cls.assign_package_to_resources( + package=package, + resource=conda_meta_yaml, + codebase=codebase, + package_adder=package_adder, + ) + meta_yaml_package_data = models.PackageData.from_dict(conda_meta_yaml_package_data) + if meta_yaml_package_data.dependencies: + yield from models.Dependency.from_dependent_packages( + dependent_packages=meta_yaml_package_data.dependencies, + datafile_path=conda_meta_yaml.path, + datasource_id=meta_yaml_package_data.datasource_id, + package_uid=package.package_uid, + ) + + yield conda_meta_yaml + + @classmethod + def assemble_from_meta_yaml_only(cls, package_data, resource, codebase, package_adder=models.add_to_package): + """ + Assemble and yeild package, dependencies and the meta YAML `resource` from + it's `package_data`, and also assign resources to the package. + """ + if not package_data.purl: + return + + package = models.Package.from_package_data( + package_data=package_data, + datafile_path=resource.path, + ) + package.populate_license_fields() + yield package + + dependent_packages = package_data.dependencies + if dependent_packages: + yield from models.Dependency.from_dependent_packages( + dependent_packages=dependent_packages, + datafile_path=resource.path, + datasource_id=package_data.datasource_id, + package_uid=package.package_uid, + ) + + CondaMetaYamlHandler.assign_package_to_resources( + package=package, + resource=resource, + codebase=codebase, + package_adder=package_adder, + ) + yield resource + @classmethod def check_valid_packages_dir_name(cls, package_dir_resource, resource, codebase): """ From 1cd58e5cf4e50d3048c010ec55028791c7870522 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Tue, 14 Jan 2025 20:30:11 +0530 Subject: [PATCH 29/29] Refactor code using resource.extracted_from function Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/packagedcode/models.py b/src/packagedcode/models.py index 45a2f6d4de6..030f30a34ff 100644 --- a/src/packagedcode/models.py +++ b/src/packagedcode/models.py @@ -1200,8 +1200,7 @@ def assign_package_to_resources(cls, package, resource, codebase, package_adder= # update `for_packages` of a codebase resource. package_uid = package.package_uid if resource.path.endswith("-extract"): - archive_resource_path = resource.path.removesuffix("-extract") - archive_resource = codebase.get_resource(archive_resource_path) + archive_resource = resource.extracted_from(codebase) if archive_resource: package_adder(package_uid, archive_resource, codebase)