Skip to content

Commit ec9eccd

Browse files
mingxin-zhengpre-commit-ci[bot]wyli
authored
Copyright checks in notebook and script files (#1145)
Signed-off-by: Mingxin Zheng <18563433+mingxin-zheng@users.noreply.github.com> Adds the copyright check mentioned #1143 . ### Description A few sentences describing the changes proposed in this pull request. ### Checks <!--- Put an `x` in all the boxes that apply, and remove the not applicable items --> - [x] Avoid including large-size files in the PR. - [x] Clean up long text outputs from code cells in the notebook. - [x] Remove private info such as user name and private key from the notebook and script files. - [x] Ensure (1) hyperlinks and markdown anchors are working (2) use relative paths for tutorial repo files (3) put figure and graphs in the `./figure` folder - [x] Notebook runs automatically `./runner.sh -t <path to .ipynb file>` Signed-off-by: Mingxin Zheng <18563433+mingxin-zheng@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Wenqi Li <831580+wyli@users.noreply.github.com>
1 parent 4825768 commit ec9eccd

File tree

2 files changed

+111
-12
lines changed

2 files changed

+111
-12
lines changed

.github/workflows/copyright.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: build
2+
3+
on:
4+
# quick tests for every pull request
5+
push:
6+
branches:
7+
- main
8+
pull_request:
9+
10+
jobs:
11+
# caching of these jobs:
12+
# - docker-20-03-py3-pip- (shared)
13+
# - ubuntu py37 pip-
14+
# - os-latest-pip- (shared)
15+
copyright:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v3
19+
- name: Set up Python 3.8
20+
uses: actions/setup-python@v3
21+
with:
22+
python-version: 3.8
23+
- name: cache weekly timestamp
24+
id: pip-cache
25+
run: |
26+
echo "::set-output name=datew::$(date '+%Y-%V')"
27+
- name: cache for pip
28+
uses: actions/cache@v3
29+
id: cache
30+
with:
31+
path: ~/.cache/pip
32+
key: ${{ runner.os }}-pip-${{ steps.pip-cache.outputs.datew }}
33+
- name: Install dependencies
34+
run: |
35+
python -m pip install --upgrade pip wheel
36+
python -m pip install -r https://raw.githubusercontent.com/Project-MONAI/MONAI/dev/requirements-dev.txt
37+
python -m pip install -r requirements.txt
38+
- name: Copyright check
39+
run: |
40+
$(pwd)/runner.sh --no-run --no-checks --copyright

runner.sh

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22

3-
# Copyright 2020 MONAI Consortium
3+
# Copyright (c) MONAI Consortium
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
66
# You may obtain a copy of the License at
@@ -100,13 +100,16 @@ then
100100
fi
101101

102102
doChecks=true
103+
doCopyright=false
103104
doRun=true
104105
autofix=false
105106
failfast=false
106107
pattern=""
107108

108109
kernelspec="python3"
109110

111+
PY_EXE=${MONAI_PY_EXE:-$(which python)}
112+
110113
function print_usage {
111114
echo "runner.sh [--no-run] [--no-checks] [--autofix] [-f/--failfast] [-p/--pattern <find pattern>] [-h/--help]"
112115
echo "[-v/--version]"
@@ -118,18 +121,19 @@ function print_usage {
118121
echo " --no-run : don't run notebooks"
119122
echo " --no-checks : don't run code checks"
120123
echo " --autofix : autofix where possible"
124+
echo " --copyright : check whether every source code and notebook has a copyright header"
121125
echo " -f, --failfast : stop on first error"
122126
echo " -p, --pattern : pattern of files to be run (added to \`find . -type f -name *.ipynb -and ! -wholename *.ipynb_checkpoints*\`)"
123127
echo " -h, --help : show this help message and exit"
124-
echo " -t, --test : shortcut to run a single notebook using pattern `-and -wholename`"
128+
echo " -t, --test : shortcut to run a single notebook using pattern `-and -wholename`"
125129
echo " -v, --version : show MONAI and system version information and exit"
126130
echo ""
127131
echo "Examples:"
128132
echo "./runner.sh # run full tests (${green}recommended before making pull requests${noColor})."
129133
echo "./runner.sh --no-run # don't run the notebooks."
130134
echo "./runner.sh --no-checks # don't run code checks."
131-
echo "./runner.sh -t 2d_classification/mednist_tutorial.ipynb"
132-
echo " # test if notebook mednist_tutorial.ipynb runs properly in test."
135+
echo "./runner.sh -t 2d_classification/mednist_tutorial.ipynb"
136+
echo " # test if notebook mednist_tutorial.ipynb runs properly in test."
133137
echo "./runner.sh --pattern \"-and \( -name '*read*' -or -name '*load*' \) -and ! -wholename '*acceleration*'\""
134138
echo " # check filenames containing \"read\" or \"load\", but not if the"
135139
echo " whole path contains \"deepgrow\"."
@@ -138,6 +142,7 @@ function print_usage {
138142
echo "${separator}For bug reports, questions, and discussions, please file an issue at:"
139143
echo " https://github.com/Project-MONAI/MONAI/issues/new/choose"
140144
echo ""
145+
echo "To choose an alternative python executable, set the environmental variable, \"MONAI_PY_EXE\"."
141146
}
142147

143148
function print_style_fail_msg() {
@@ -162,6 +167,9 @@ do
162167
--autofix)
163168
autofix=true
164169
;;
170+
--copyright)
171+
doCopyright=true
172+
;;
165173
-f|--failfast)
166174
failfast=true
167175
;;
@@ -178,11 +186,11 @@ do
178186
print_usage
179187
exit 0
180188
;;
181-
-t|--test)
182-
pattern+="-and -wholename ./$2"
183-
echo $pattern
184-
shift
185-
;;
189+
-t|--test)
190+
pattern+="-and -wholename ./$2"
191+
echo $pattern
192+
shift
193+
;;
186194
-v|--version)
187195
print_version
188196
exit 1
@@ -229,6 +237,58 @@ if [ $doChecks = true ]; then
229237
fi
230238
fi
231239

240+
function verify_notebook_has_key_in_cell() {
241+
fname=$1
242+
key=$2
243+
cell=$3
244+
celltype=$4
245+
${PY_EXE} - << END
246+
import nbformat
247+
import re
248+
249+
with open("$fname", "r") as f:
250+
contents = nbformat.reads(f.read(), as_version=4)
251+
cell = contents.cells[int("$cell")]
252+
result = "true" if cell.cell_type == "$celltype" and re.search("$key", cell.source) else "false"
253+
print(result)
254+
END
255+
}
256+
257+
if [ $doCopyright = true ]
258+
then
259+
check_installed nbformat
260+
# check copyright headers
261+
copyright_bad=0
262+
copyright_all=0
263+
license="http://www.apache.org/licenses/LICENSE-2.0"
264+
while read -r fname; do
265+
copyright_all=$((copyright_all + 1))
266+
if ! grep "$license" "$fname" > /dev/null; then
267+
print_error_msg "Missing the license header in file: $fname"
268+
copyright_bad=$((copyright_bad + 1))
269+
fi
270+
done <<< "$(find "$(pwd)" -type f \
271+
-and -name "*.py" -or -name "*.sh" -or -name "*.cpp" -or -name "*.cu" -or -name "*.h")"
272+
273+
while read -r fname; do
274+
copyright_all=$((copyright_all + 1))
275+
if [[ $(verify_notebook_has_key_in_cell "$fname" "$license" 0 "markdown" ) != true ]]; then
276+
print_error_msg "Missing the license header the first markdown cell of file: $fname"
277+
copyright_bad=$((copyright_bad + 1))
278+
fi
279+
done <<< "$(find "$(pwd)" -type f -name "*.ipynb" -and ! -wholename "*.ipynb_checkpoints*")"
280+
281+
if [[ ${copyright_bad} -eq 0 ]];
282+
then
283+
echo "${green}Source code copyright headers checked ($copyright_all).${noColor}"
284+
else
285+
echo "Please add the licensing header to the file ($copyright_bad of $copyright_all files)."
286+
echo " See also: https://github.com/Project-MONAI/tutorials/blob/main/CONTRIBUTING.md#add-license"
287+
echo ""
288+
exit 1
289+
fi
290+
fi
291+
232292

233293
base_path="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
234294
cd "${base_path}"
@@ -246,14 +306,13 @@ function replace_text {
246306
[ ! -z "$after" ] && echo After: && echo "$after"
247307
}
248308

249-
# Get notebooks (pattern is "-and -name '*' -and ! -wholename '*federated_learning*'"
250-
# unless user specifies otherwise)
309+
# Get notebooks (pattern is an empty string unless the user specifies otherwise)
251310
files=($(echo $pattern | xargs find . -type f -name "*.ipynb" -and ! -wholename "*.ipynb_checkpoints*"))
252311
if [[ $files == "" ]]; then
253312
print_error_msg "No files match pattern"
254313
exit 0
255314
fi
256-
echo "Files to be tested:"
315+
echo "Notebook files to be tested:"
257316
for i in "${files[@]}"; do echo $i; done
258317

259318
# Keep track of number of passed tests. Use a trap to print results on exit

0 commit comments

Comments
 (0)