From 7738635fac0cc2d3ec42f7e1f0e914ba6f5b9f1a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 12 Apr 2026 20:12:23 -0700 Subject: [PATCH 1/4] Systematically correct SPDX-License-Identifier: Apache-2.0 --- cuda_core/cuda/core/_include/layout.hpp | 2 +- cuda_core/cuda/core/_include/utility.hpp | 2 +- cuda_core/cuda/core/_utils/__init__.py | 2 +- cuda_core/cuda/core/_utils/clear_error_support.py | 2 +- cuda_core/cuda/core/_utils/driver_cu_result_explanations.py | 2 +- .../cuda/core/_utils/driver_cu_result_explanations_frozen.py | 2 +- cuda_core/cuda/core/_utils/enum_explanations_helpers.py | 2 +- cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py | 2 +- .../cuda/core/_utils/runtime_cuda_error_explanations_frozen.py | 2 +- cuda_core/pytest.ini | 2 +- cuda_core/tests/cython/test_cython.py | 2 +- cuda_core/tests/cython/test_get_cuda_native_handle.pyx | 2 +- cuda_core/tests/graph/test_device_launch.py | 2 +- cuda_core/tests/graph/test_graph_builder.py | 2 +- cuda_core/tests/graph/test_graph_builder_conditional.py | 2 +- cuda_core/tests/graph/test_graph_memory_resource.py | 2 +- cuda_core/tests/graph/test_graph_update.py | 2 +- cuda_core/tests/graph/test_graphdef.py | 2 +- cuda_core/tests/graph/test_graphdef_errors.py | 2 +- cuda_core/tests/graph/test_graphdef_integration.py | 2 +- cuda_core/tests/graph/test_graphdef_lifetime.py | 2 +- cuda_core/tests/graph/test_graphdef_mutation.py | 2 +- cuda_core/tests/graph/test_options.py | 2 +- cuda_core/tests/helpers/collection_interface_testers.py | 2 +- cuda_core/tests/helpers/graph_kernels.py | 2 +- cuda_core/tests/helpers/marks.py | 2 +- cuda_core/tests/test_cuda_utils.py | 2 +- cuda_core/tests/test_helpers.py | 2 +- cuda_core/tests/test_linker.py | 2 +- cuda_core/tests/test_optional_dependency_imports.py | 2 +- cuda_core/tests/test_program.py | 2 +- cuda_core/tests/test_utils.py | 2 +- cuda_core/tests/test_utils_enum_explanations_helpers.py | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cuda_core/cuda/core/_include/layout.hpp b/cuda_core/cuda/core/_include/layout.hpp index ad3a2c6ffd..b5da219df3 100644 --- a/cuda_core/cuda/core/_include/layout.hpp +++ b/cuda_core/cuda/core/_include/layout.hpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. // All rights reserved. // -// SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +// SPDX-License-Identifier: Apache-2.0 #ifndef CUDA_CORE_LAYOUT_HPP #define CUDA_CORE_LAYOUT_HPP diff --git a/cuda_core/cuda/core/_include/utility.hpp b/cuda_core/cuda/core/_include/utility.hpp index aa83a465e3..64b357ac32 100644 --- a/cuda_core/cuda/core/_include/utility.hpp +++ b/cuda_core/cuda/core/_include/utility.hpp @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // -// SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +// SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/cuda_core/cuda/core/_utils/__init__.py b/cuda_core/cuda/core/_utils/__init__.py index bd8faf14fa..79599c77db 100644 --- a/cuda_core/cuda/core/_utils/__init__.py +++ b/cuda_core/cuda/core/_utils/__init__.py @@ -1,3 +1,3 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 diff --git a/cuda_core/cuda/core/_utils/clear_error_support.py b/cuda_core/cuda/core/_utils/clear_error_support.py index 0410e7aa2f..56c74ea955 100644 --- a/cuda_core/cuda/core/_utils/clear_error_support.py +++ b/cuda_core/cuda/core/_utils/clear_error_support.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 def assert_type(obj, expected_type): diff --git a/cuda_core/cuda/core/_utils/driver_cu_result_explanations.py b/cuda_core/cuda/core/_utils/driver_cu_result_explanations.py index f4894d7563..76c6cc534a 100644 --- a/cuda_core/cuda/core/_utils/driver_cu_result_explanations.py +++ b/cuda_core/cuda/core/_utils/driver_cu_result_explanations.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 from cuda.bindings import driver from cuda.core._utils.enum_explanations_helpers import get_best_available_explanations diff --git a/cuda_core/cuda/core/_utils/driver_cu_result_explanations_frozen.py b/cuda_core/cuda/core/_utils/driver_cu_result_explanations_frozen.py index e396afaa79..567b969038 100644 --- a/cuda_core/cuda/core/_utils/driver_cu_result_explanations_frozen.py +++ b/cuda_core/cuda/core/_utils/driver_cu_result_explanations_frozen.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 # CUDA Toolkit v13.1.1 _FALLBACK_EXPLANATIONS = { diff --git a/cuda_core/cuda/core/_utils/enum_explanations_helpers.py b/cuda_core/cuda/core/_utils/enum_explanations_helpers.py index a176de73d1..c7927e71e4 100644 --- a/cuda_core/cuda/core/_utils/enum_explanations_helpers.py +++ b/cuda_core/cuda/core/_utils/enum_explanations_helpers.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Internal support for error-enum explanations. diff --git a/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py b/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py index ab5be10e2d..1fa2226c54 100644 --- a/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py +++ b/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 from cuda.bindings import runtime from cuda.core._utils.enum_explanations_helpers import get_best_available_explanations diff --git a/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations_frozen.py b/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations_frozen.py index 497b2ad20d..017c408740 100644 --- a/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations_frozen.py +++ b/cuda_core/cuda/core/_utils/runtime_cuda_error_explanations_frozen.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 # CUDA Toolkit v13.1.1 _FALLBACK_EXPLANATIONS = { diff --git a/cuda_core/pytest.ini b/cuda_core/pytest.ini index df1963f383..41bf0d9c4f 100644 --- a/cuda_core/pytest.ini +++ b/cuda_core/pytest.ini @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 [pytest] addopts = --showlocals diff --git a/cuda_core/tests/cython/test_cython.py b/cuda_core/tests/cython/test_cython.py index a118249043..87b97e8a2a 100644 --- a/cuda_core/tests/cython/test_cython.py +++ b/cuda_core/tests/cython/test_cython.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import functools import importlib diff --git a/cuda_core/tests/cython/test_get_cuda_native_handle.pyx b/cuda_core/tests/cython/test_get_cuda_native_handle.pyx index 2b105e13ae..1480a3b96b 100644 --- a/cuda_core/tests/cython/test_get_cuda_native_handle.pyx +++ b/cuda_core/tests/cython/test_get_cuda_native_handle.pyx @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 # distutils: language = c++ # distutils: extra_compile_args = -std=c++17 diff --git a/cuda_core/tests/graph/test_device_launch.py b/cuda_core/tests/graph/test_device_launch.py index 21e58cb673..0bd4ba1263 100644 --- a/cuda_core/tests/graph/test_device_launch.py +++ b/cuda_core/tests/graph/test_device_launch.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for device-side graph launch (GPU kernel launching a CUDA graph).""" diff --git a/cuda_core/tests/graph/test_graph_builder.py b/cuda_core/tests/graph/test_graph_builder.py index 3f9b8e91d1..aca5a83ecf 100644 --- a/cuda_core/tests/graph/test_graph_builder.py +++ b/cuda_core/tests/graph/test_graph_builder.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """GraphBuilder stream capture tests.""" diff --git a/cuda_core/tests/graph/test_graph_builder_conditional.py b/cuda_core/tests/graph/test_graph_builder_conditional.py index e34186fb14..1446b8b3c4 100644 --- a/cuda_core/tests/graph/test_graph_builder_conditional.py +++ b/cuda_core/tests/graph/test_graph_builder_conditional.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for GraphBuilder conditional node capture (if, if-else, switch, while).""" diff --git a/cuda_core/tests/graph/test_graph_memory_resource.py b/cuda_core/tests/graph/test_graph_memory_resource.py index fe47ef2d68..13e6745d74 100644 --- a/cuda_core/tests/graph/test_graph_memory_resource.py +++ b/cuda_core/tests/graph/test_graph_memory_resource.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for GraphMemoryResource allocation and attributes during graph capture.""" diff --git a/cuda_core/tests/graph/test_graph_update.py b/cuda_core/tests/graph/test_graph_update.py index 8e7881f8e9..d06333afff 100644 --- a/cuda_core/tests/graph/test_graph_update.py +++ b/cuda_core/tests/graph/test_graph_update.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for whole-graph update (Graph.update).""" diff --git a/cuda_core/tests/graph/test_graphdef.py b/cuda_core/tests/graph/test_graphdef.py index b5c76013bd..e81c0b03b9 100644 --- a/cuda_core/tests/graph/test_graphdef.py +++ b/cuda_core/tests/graph/test_graphdef.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for GraphDef topology, node types, instantiation, and execution.""" diff --git a/cuda_core/tests/graph/test_graphdef_errors.py b/cuda_core/tests/graph/test_graphdef_errors.py index b8fe1f6dc5..54b28d7a5c 100644 --- a/cuda_core/tests/graph/test_graphdef_errors.py +++ b/cuda_core/tests/graph/test_graphdef_errors.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for GraphDef input validation, error handling, and edge cases.""" diff --git a/cuda_core/tests/graph/test_graphdef_integration.py b/cuda_core/tests/graph/test_graphdef_integration.py index 243c93433c..3fc0263c95 100644 --- a/cuda_core/tests/graph/test_graphdef_integration.py +++ b/cuda_core/tests/graph/test_graphdef_integration.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """End-to-end integration tests exercising all GraphDef node types in realistic scenarios.""" diff --git a/cuda_core/tests/graph/test_graphdef_lifetime.py b/cuda_core/tests/graph/test_graphdef_lifetime.py index 21d519bb89..a9b3003077 100644 --- a/cuda_core/tests/graph/test_graphdef_lifetime.py +++ b/cuda_core/tests/graph/test_graphdef_lifetime.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for GraphDef resource lifetime management and RAII correctness.""" diff --git a/cuda_core/tests/graph/test_graphdef_mutation.py b/cuda_core/tests/graph/test_graphdef_mutation.py index 5c8d9434dd..2f9dd442da 100644 --- a/cuda_core/tests/graph/test_graphdef_mutation.py +++ b/cuda_core/tests/graph/test_graphdef_mutation.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Tests for mutating a graph definition (edge changes, node removal).""" diff --git a/cuda_core/tests/graph/test_options.py b/cuda_core/tests/graph/test_options.py index 33d647f6fe..0d10db459d 100644 --- a/cuda_core/tests/graph/test_options.py +++ b/cuda_core/tests/graph/test_options.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Graph options and build mode tests.""" diff --git a/cuda_core/tests/helpers/collection_interface_testers.py b/cuda_core/tests/helpers/collection_interface_testers.py index d9b5ee2cd0..5197e475c1 100644 --- a/cuda_core/tests/helpers/collection_interface_testers.py +++ b/cuda_core/tests/helpers/collection_interface_testers.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Reusable helpers to verify collections.abc protocol conformance.""" diff --git a/cuda_core/tests/helpers/graph_kernels.py b/cuda_core/tests/helpers/graph_kernels.py index 657d7509b2..c7d0ed766a 100644 --- a/cuda_core/tests/helpers/graph_kernels.py +++ b/cuda_core/tests/helpers/graph_kernels.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Shared kernel compilation helpers for graph tests.""" diff --git a/cuda_core/tests/helpers/marks.py b/cuda_core/tests/helpers/marks.py index 5474c862ba..53fcc544eb 100644 --- a/cuda_core/tests/helpers/marks.py +++ b/cuda_core/tests/helpers/marks.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 """Reusable pytest marks for cuda_core tests.""" diff --git a/cuda_core/tests/test_cuda_utils.py b/cuda_core/tests/test_cuda_utils.py index 1357ca3a12..be22e57998 100644 --- a/cuda_core/tests/test_cuda_utils.py +++ b/cuda_core/tests/test_cuda_utils.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import dataclasses diff --git a/cuda_core/tests/test_helpers.py b/cuda_core/tests/test_helpers.py index bd13ed5067..23a5b71c85 100644 --- a/cuda_core/tests/test_helpers.py +++ b/cuda_core/tests/test_helpers.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import time diff --git a/cuda_core/tests/test_linker.py b/cuda_core/tests/test_linker.py index c36903ab32..30a6a03349 100644 --- a/cuda_core/tests/test_linker.py +++ b/cuda_core/tests/test_linker.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/cuda_core/tests/test_optional_dependency_imports.py b/cuda_core/tests/test_optional_dependency_imports.py index 730c6e7834..02edcc9839 100644 --- a/cuda_core/tests/test_optional_dependency_imports.py +++ b/cuda_core/tests/test_optional_dependency_imports.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/cuda_core/tests/test_program.py b/cuda_core/tests/test_program.py index ac40fb735d..a062f3714e 100644 --- a/cuda_core/tests/test_program.py +++ b/cuda_core/tests/test_program.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import contextlib import re diff --git a/cuda_core/tests/test_utils.py b/cuda_core/tests/test_utils.py index 59829f8fb3..4bdebcbde3 100644 --- a/cuda_core/tests/test_utils.py +++ b/cuda_core/tests/test_utils.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import ctypes import math diff --git a/cuda_core/tests/test_utils_enum_explanations_helpers.py b/cuda_core/tests/test_utils_enum_explanations_helpers.py index d46355aefd..6d4c9e32b8 100644 --- a/cuda_core/tests/test_utils_enum_explanations_helpers.py +++ b/cuda_core/tests/test_utils_enum_explanations_helpers.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-License-Identifier: Apache-2.0 import importlib import sys From 47eaed9e4c22ec492d952fe27fde8897b1ff71a1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 12 Apr 2026 20:41:01 -0700 Subject: [PATCH 2/4] toolshed: enforce cuda_core SPDX license policy Refactor the SPDX checker so package-specific license rules can be enforced cleanly while preserving the existing autofix flow. Keep focused regression coverage alongside the toolshed script instead of in routine package test collection. Made-with: Cursor --- toolshed/check_spdx.py | 145 ++++++++++++++++++++++++++---------- toolshed/test_check_spdx.py | 91 ++++++++++++++++++++++ 2 files changed, 196 insertions(+), 40 deletions(-) create mode 100644 toolshed/test_check_spdx.py diff --git a/toolshed/check_spdx.py b/toolshed/check_spdx.py index b404b78e30..1931cb2251 100644 --- a/toolshed/check_spdx.py +++ b/toolshed/check_spdx.py @@ -9,12 +9,14 @@ import pathspec -# Intentionally puzzling together EXPECTED_SPDX_BYTES so that we don't overlook -# if the identifiers are missing in this file. -EXPECTED_SPDX_BYTES = ( - b"-".join((b"SPDX", b"License", b"Identifier: ")), - b"-".join((b"SPDX", b"FileCopyrightText: ")), -) +# Intentionally puzzling together SPDX prefixes so that we don't overlook if the +# identifiers are missing in this file. +SPDX_LICENSE_IDENTIFIER_PREFIX = b"-".join((b"SPDX", b"License", b"Identifier: ")) +SPDX_FILE_COPYRIGHT_TEXT_PREFIX = b"-".join((b"SPDX", b"FileCopyrightText: ")) + +LICENSE_IDENTIFIER_REGEX = re.compile(re.escape(SPDX_LICENSE_IDENTIFIER_PREFIX) + rb"(?P[^\r\n]+)") + +EXPECTED_LICENSE_IDENTIFIERS = (("cuda_core/", "Apache-2.0"),) SPDX_IGNORE_FILENAME = ".spdx-ignore" @@ -47,6 +49,91 @@ def is_staged(filepath): return process.stdout.strip() != "" +def normalize_repo_path(filepath): + normalized_path = filepath.replace("\\", "/") + while normalized_path.startswith("./"): + normalized_path = normalized_path[2:] + return normalized_path + + +def get_expected_license_identifier(filepath): + normalized_path = normalize_repo_path(filepath) + for prefix, license_identifier in EXPECTED_LICENSE_IDENTIFIERS: + if normalized_path.startswith(prefix): + return license_identifier + return None + + +def validate_required_spdx_field(filepath, blob, expected_bytes): + if expected_bytes in blob: + return True + print(f"MISSING {expected_bytes.decode()}{filepath!r}") + return False + + +def extract_license_identifier(blob): + match = LICENSE_IDENTIFIER_REGEX.search(blob) + if match is None: + return None + try: + return match.group("license_identifier").decode("ascii") + except UnicodeDecodeError: + return None + + +def validate_license_identifier(filepath, blob): + license_identifier = extract_license_identifier(blob) + if license_identifier is None: + print(f"MISSING valid SPDX license identifier in {filepath!r}") + return False + + expected_license_identifier = get_expected_license_identifier(filepath) + if expected_license_identifier is None: + return True + + if license_identifier != expected_license_identifier: + print( + f"INVALID SPDX license identifier {license_identifier!r} " + f"(expected {expected_license_identifier!r}) in {filepath!r}" + ) + return False + + return True + + +def validate_or_fix_copyright(filepath, blob, fix): + match = re.search(COPYRIGHT_REGEX, blob) + if match is None: + print(f"MISSING valid copyright line in {filepath!r}") + return False, blob + + years = match.group("years").decode() + if "-" in years: + start_year, end_year = years.split("-", 1) + if int(start_year) > int(end_year): + print(f"INVALID copyright years {years!r} in {filepath!r}") + return False, blob + else: + start_year = end_year = years + + if not is_staged(filepath) or int(end_year) >= int(CURRENT_YEAR): + return True, blob + + print(f"OUTDATED copyright {years!r} (expected {CURRENT_YEAR!r}) in {filepath!r}") + if not fix: + return False, blob + + new_years = f"{start_year}-{CURRENT_YEAR}" + return ( + False, + re.sub( + COPYRIGHT_REGEX, + COPYRIGHT_SUB.format(new_years).encode("ascii"), + blob, + ), + ) + + def find_or_fix_spdx(filepath, fix): with open(filepath, "rb") as f: blob = f.read() @@ -54,44 +141,22 @@ def find_or_fix_spdx(filepath, fix): return True good = True - for expected_bytes in EXPECTED_SPDX_BYTES: - if expected_bytes not in blob: - print(f"MISSING {expected_bytes.decode()}{filepath!r}") - good = False - continue - - match = re.search(COPYRIGHT_REGEX, blob) - if match is None: - print(f"MISSING valid copyright line in {filepath!r}") - good = False - continue + has_license_identifier = validate_required_spdx_field(filepath, blob, SPDX_LICENSE_IDENTIFIER_PREFIX) + has_copyright = validate_required_spdx_field(filepath, blob, SPDX_FILE_COPYRIGHT_TEXT_PREFIX) - years = match.group("years").decode() - if "-" in years: - start_year, end_year = years.split("-", 1) - if int(start_year) > int(end_year): - print(f"INVALID copyright years {years!r} in {filepath!r}") - good = False - continue - else: - start_year = end_year = years + if not has_license_identifier or not validate_license_identifier(filepath, blob): + good = False - staged = is_staged(filepath) - - if staged and int(end_year) < int(CURRENT_YEAR): - print(f"OUTDATED copyright {years!r} (expected {CURRENT_YEAR!r}) in {filepath!r}") + if not has_copyright: + good = False + else: + copyright_ok, updated_blob = validate_or_fix_copyright(filepath, blob, fix) + if updated_blob != blob: + with open(filepath, "wb") as f: + f.write(updated_blob) + if not copyright_ok: good = False - if fix: - new_years = f"{start_year}-{CURRENT_YEAR}" - blob = re.sub( - COPYRIGHT_REGEX, - COPYRIGHT_SUB.format(new_years).encode("ascii"), - blob, - ) - with open(filepath, "wb") as f: - f.write(blob) - return good diff --git a/toolshed/test_check_spdx.py b/toolshed/test_check_spdx.py new file mode 100644 index 0000000000..3ae402bcbe --- /dev/null +++ b/toolshed/test_check_spdx.py @@ -0,0 +1,91 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +import importlib.util +import sys +from pathlib import Path +from types import ModuleType + + +def _install_pathspec_stub(): + if "pathspec" in sys.modules: + return + + class _StubSpec: + def match_file(self, _filepath): + return False + + class _StubPathSpec: + @staticmethod + def from_lines(_pattern_type, _lines): + return _StubSpec() + + module = ModuleType("pathspec") + module.PathSpec = _StubPathSpec + sys.modules["pathspec"] = module + + +def _load_check_spdx(): + check_spdx_path = Path(__file__).resolve().with_name("check_spdx.py") + spec = importlib.util.spec_from_file_location("check_spdx", check_spdx_path) + assert spec is not None + assert spec.loader is not None + _install_pathspec_stub() + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +check_spdx = _load_check_spdx() + + +def _write_spdx_file(root, relative_path, license_identifier, *, years="2025-2026"): + path = root / relative_path + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text( + ( + f"# SPDX-FileCopyrightText: Copyright (c) {years} NVIDIA CORPORATION & AFFILIATES. " + "All rights reserved.\n" + f"# SPDX-License-Identifier: {license_identifier}\n" + "\n" + "print('hello')\n" + ), + encoding="ascii", + ) + return path + + +def test_get_expected_license_identifier_normalizes_windows_paths(): + assert check_spdx.get_expected_license_identifier(r".\cuda_core\example.py") == "Apache-2.0" + + +def test_find_or_fix_spdx_rejects_non_apache_license_under_cuda_core(tmp_path, monkeypatch, capsys): + monkeypatch.chdir(tmp_path) + monkeypatch.setattr(check_spdx, "is_staged", lambda _: False) + _write_spdx_file(tmp_path, "cuda_core/example.py", "LicenseRef-NVIDIA-SOFTWARE-LICENSE") + + assert not check_spdx.find_or_fix_spdx("cuda_core/example.py", fix=False) + + assert "expected 'Apache-2.0'" in capsys.readouterr().out + + +def test_find_or_fix_spdx_allows_non_apache_license_outside_cuda_core(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + monkeypatch.setattr(check_spdx, "is_staged", lambda _: False) + _write_spdx_file(tmp_path, "cuda_bindings/example.py", "LicenseRef-NVIDIA-SOFTWARE-LICENSE") + + assert check_spdx.find_or_fix_spdx("cuda_bindings/example.py", fix=False) + + +def test_find_or_fix_spdx_updates_outdated_copyright_when_fix_requested(tmp_path, monkeypatch, capsys): + monkeypatch.chdir(tmp_path) + monkeypatch.setattr(check_spdx, "CURRENT_YEAR", "2026") + monkeypatch.setattr(check_spdx, "is_staged", lambda _: True) + path = _write_spdx_file(tmp_path, "cuda_core/example.py", "Apache-2.0", years="2024") + + assert not check_spdx.find_or_fix_spdx("cuda_core/example.py", fix=True) + + assert "OUTDATED copyright '2024' (expected '2026')" in capsys.readouterr().out + assert "Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved." in path.read_text( + encoding="ascii" + ) From 36a491404f46b2daa7a8a8e4b57a62a70006211f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 13 Apr 2026 11:59:48 -0700 Subject: [PATCH 3/4] Remove toolshed/test_check_spdx.py (too much trouble adding it to the CI, but it will bit-rot if untested). --- toolshed/test_check_spdx.py | 91 ------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 toolshed/test_check_spdx.py diff --git a/toolshed/test_check_spdx.py b/toolshed/test_check_spdx.py deleted file mode 100644 index 3ae402bcbe..0000000000 --- a/toolshed/test_check_spdx.py +++ /dev/null @@ -1,91 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -import importlib.util -import sys -from pathlib import Path -from types import ModuleType - - -def _install_pathspec_stub(): - if "pathspec" in sys.modules: - return - - class _StubSpec: - def match_file(self, _filepath): - return False - - class _StubPathSpec: - @staticmethod - def from_lines(_pattern_type, _lines): - return _StubSpec() - - module = ModuleType("pathspec") - module.PathSpec = _StubPathSpec - sys.modules["pathspec"] = module - - -def _load_check_spdx(): - check_spdx_path = Path(__file__).resolve().with_name("check_spdx.py") - spec = importlib.util.spec_from_file_location("check_spdx", check_spdx_path) - assert spec is not None - assert spec.loader is not None - _install_pathspec_stub() - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - return module - - -check_spdx = _load_check_spdx() - - -def _write_spdx_file(root, relative_path, license_identifier, *, years="2025-2026"): - path = root / relative_path - path.parent.mkdir(parents=True, exist_ok=True) - path.write_text( - ( - f"# SPDX-FileCopyrightText: Copyright (c) {years} NVIDIA CORPORATION & AFFILIATES. " - "All rights reserved.\n" - f"# SPDX-License-Identifier: {license_identifier}\n" - "\n" - "print('hello')\n" - ), - encoding="ascii", - ) - return path - - -def test_get_expected_license_identifier_normalizes_windows_paths(): - assert check_spdx.get_expected_license_identifier(r".\cuda_core\example.py") == "Apache-2.0" - - -def test_find_or_fix_spdx_rejects_non_apache_license_under_cuda_core(tmp_path, monkeypatch, capsys): - monkeypatch.chdir(tmp_path) - monkeypatch.setattr(check_spdx, "is_staged", lambda _: False) - _write_spdx_file(tmp_path, "cuda_core/example.py", "LicenseRef-NVIDIA-SOFTWARE-LICENSE") - - assert not check_spdx.find_or_fix_spdx("cuda_core/example.py", fix=False) - - assert "expected 'Apache-2.0'" in capsys.readouterr().out - - -def test_find_or_fix_spdx_allows_non_apache_license_outside_cuda_core(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) - monkeypatch.setattr(check_spdx, "is_staged", lambda _: False) - _write_spdx_file(tmp_path, "cuda_bindings/example.py", "LicenseRef-NVIDIA-SOFTWARE-LICENSE") - - assert check_spdx.find_or_fix_spdx("cuda_bindings/example.py", fix=False) - - -def test_find_or_fix_spdx_updates_outdated_copyright_when_fix_requested(tmp_path, monkeypatch, capsys): - monkeypatch.chdir(tmp_path) - monkeypatch.setattr(check_spdx, "CURRENT_YEAR", "2026") - monkeypatch.setattr(check_spdx, "is_staged", lambda _: True) - path = _write_spdx_file(tmp_path, "cuda_core/example.py", "Apache-2.0", years="2024") - - assert not check_spdx.find_or_fix_spdx("cuda_core/example.py", fix=True) - - assert "OUTDATED copyright '2024' (expected '2026')" in capsys.readouterr().out - assert "Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved." in path.read_text( - encoding="ascii" - ) From eef39026ffd10df981bd65863fe36c00906c844e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 13 Apr 2026 12:07:23 -0700 Subject: [PATCH 4/4] toolshed: normalize SPDX paths with PureWindowsPath Use a standard-library path normalizer so repo-prefix checks treat Windows-style paths consistently on any host. Document why os.path.normpath is not suitable for this forward-slash prefix comparison. Made-with: Cursor --- toolshed/check_spdx.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/toolshed/check_spdx.py b/toolshed/check_spdx.py index 1931cb2251..292637817e 100644 --- a/toolshed/check_spdx.py +++ b/toolshed/check_spdx.py @@ -6,6 +6,7 @@ import re import subprocess import sys +from pathlib import PureWindowsPath import pathspec @@ -50,10 +51,11 @@ def is_staged(filepath): def normalize_repo_path(filepath): - normalized_path = filepath.replace("\\", "/") - while normalized_path.startswith("./"): - normalized_path = normalized_path[2:] - return normalized_path + # We compare against repo prefixes like "cuda_core/" regardless of host OS. + # os.path.normpath is host-dependent: on POSIX it leaves "\" untouched, and + # on Windows it normalizes to "\" separators, so neither gives a stable + # forward-slash form for this prefix check. + return PureWindowsPath(filepath).as_posix() def get_expected_license_identifier(filepath):