Skip to content
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ repos:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: local
hooks:
- id: check-spdx
name: Check SPDX Headers
entry: python ./toolshed/check_spdx.py
language: python
additional_dependencies:
- pathspec==0.12.1
34 changes: 34 additions & 0 deletions .spdx-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
LICENSE
LICENSE.numba
*.html
*.json
*.md
*.png
*.svg
*.rst
*.txt
*.ptx
*.pyc
requirements*.txt

# Documentation build artifacts
docs/build/*

# Binary files
*.so
*.dll

# Build artifacts and egg-info
build/*
dist/*
*.egg-info/*

# Version files
numba_cuda/VERSION

# External CUDA SDK headers
numba_cuda/numba/cuda/include/*/cuda_*.h
numba_cuda/numba/cuda/include/*/cuda_*.hpp

# GitHub configuration files
.github/CODEOWNERS
3 changes: 3 additions & 0 deletions numba_cuda/numba/cuda/core/bytecode.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause

from collections import namedtuple, OrderedDict
import dis
import inspect
Expand Down
3 changes: 3 additions & 0 deletions numba_cuda/numba/cuda/core/environment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause

import weakref
import importlib

Expand Down
57 changes: 57 additions & 0 deletions toolshed/check_spdx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause

import os
import sys

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: ")),
)
Comment on lines +9 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: It took me a few reads to understand this, would it make more sense to use a simple string?

EXPECTED_SPDX_BYTES = b'''
SPDX-License....
'''

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vendored this from https://github.com/NVIDIA/cuda-python/blob/main/toolshed/check_spdx.py for now where happy to fix this in a follow up once it's in to prevent more conflicts 😆.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, SGTM!


SPDX_IGNORE_FILENAME = ".spdx-ignore"


def load_spdx_ignore():
if os.path.exists(SPDX_IGNORE_FILENAME):
with open(SPDX_IGNORE_FILENAME, "r", encoding="utf-8") as f:
lines = f.readlines()
else:
lines = []
lines.append(SPDX_IGNORE_FILENAME + "\n")
return pathspec.PathSpec.from_lines("gitwildmatch", lines)


def has_spdx_or_is_empty(filepath):
with open(filepath, "rb") as f:
blob = f.read()
if len(blob.strip()) == 0:
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
return good


def main(args):
assert args, "filepaths expected to be passed from pre-commit"

ignore_spec = load_spdx_ignore()

returncode = 0
for filepath in args:
if ignore_spec.match_file(filepath):
continue
if not has_spdx_or_is_empty(filepath):
returncode = 1
return returncode


if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))