Skip to content

Commit f1537d2

Browse files
authored
Add check/pylint-changed-files (#1145)
This is adapted from Cirq's script of the same name.
1 parent 898ae6c commit f1537d2

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

check/pylint-changed-files

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2025 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# Summary: run pylint on changed files using a preconfigured .pylintrc file.
18+
#
19+
# Usage:
20+
# check/pylint-changed-files [BASE_REVISION]
21+
#
22+
# You can specify a base git revision to compare against (i.e. to use when
23+
# determining whether or not a line is considered to have "changed"). To make
24+
# the tool more consistent, it actually diffs against the most recent common
25+
# ancestor of the specified id and HEAD. So if you choose 'origin/main' you're
26+
# actually diffing against the output of 'git merge-base origin/main HEAD'.
27+
#
28+
# If you don't specify a base revision, the following defaults will be tried,
29+
# in order, until one exists:
30+
#
31+
# 1. upstream/main or upstream/master
32+
# 2. origin/main or origin/master
33+
# 3. main or master
34+
#
35+
# If none exists, the script will exit with an error.
36+
#
37+
# To lint all files, use check/pylint.
38+
39+
set -o pipefail
40+
41+
# Change working directory to the repository root.
42+
thisdir=$(dirname "${BASH_SOURCE[0]:?}") || exit $?
43+
repo_dir=$(git -C "${thisdir}" rev-parse --show-toplevel) || exit $?
44+
cd "${repo_dir}" || exit $?
45+
46+
# Some old repos used "master" instead of main. Find out which one we have here.
47+
default=$(git branch --format '%(refname:short)' --list master main)
48+
49+
# Figure out which revision to compare against.
50+
if [ -n "$1" ] && [[ $1 != -* ]]; then
51+
if ! git rev-parse --verify --quiet --no-revs "$1^{commit}"; then
52+
echo -e "\033[31mNo revision '$1'.\033[0m" >&2
53+
exit 1
54+
fi
55+
rev=$1
56+
elif [ "$(git cat-file -t "upstream/${default}" 2> /dev/null)" == "commit" ]; then
57+
rev=upstream/${default}
58+
elif [ "$(git cat-file -t "origin/${default}" 2> /dev/null)" == "commit" ]; then
59+
rev=origin/${default}
60+
elif [ "$(git cat-file -t "${default}" 2> /dev/null)" == "commit" ]; then
61+
rev=${default}
62+
else
63+
echo -e "\033[31mNo default revision found to compare against. Argument #1 must be what to diff against (e.g. 'origin/main' or 'HEAD~1').\033[0m" >&2
64+
exit 1
65+
fi
66+
base=$(git merge-base "${rev}" HEAD)
67+
if [ "$(git rev-parse "${rev}")" == "${base}" ]; then
68+
echo -e "Comparing against revision '${rev}'." >&2
69+
else
70+
echo -e "Comparing against revision '${rev}' (merge base ${base})." >&2
71+
rev="${base}"
72+
fi
73+
74+
typeset -a changed
75+
IFS=$'\n' read -r -d '' -a changed < \
76+
<(git diff --name-only --diff-filter=d "${rev}" -- "*.py" \
77+
| grep -E "^(src|dev_tools).*.py$"
78+
)
79+
80+
num_changed=${#changed[@]}
81+
82+
# Run it.
83+
echo "Found ${num_changed} lintable files associated with changes." >&2
84+
if [ "${num_changed}" -eq 0 ]; then
85+
exit 0
86+
fi
87+
env PYTHONPATH=dev_tools pylint --jobs=0 --rcfile=dev_tools/conf/.pylintrc "${changed[@]}"

0 commit comments

Comments
 (0)