Skip to content

Commit 8a41849

Browse files
authored
Merge pull request #5033 from raiden-network/develop
Merge develop into master
2 parents 24701b3 + 68448ac commit 8a41849

504 files changed

Lines changed: 38871 additions & 51213 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.bumpversion_client.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.100.3
2+
current_version = 0.200.0-rc1
33
commit = True
44
tag = False
55

.circleci/config.yml

Lines changed: 83 additions & 180 deletions
Large diffs are not rendered by default.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
set -x
5+
6+
# For the first build the PR's base branch will work as a baseline,
7+
# subsequent reports will be against the PR itself. Because of
8+
# this, it is possible for a PR to undo linting fixes from another.
9+
# Example:
10+
#
11+
# 1. PR1 is opened, it does not fix any linting errors
12+
# 2. PR2 is opened against the same base branch, and merged, it
13+
# fixes linting errors
14+
# 3. PR1 is rebased on the base branch. This may introduce as many
15+
# errors as PR2 fixed without failling the build (because the
16+
# baseline is outdated).
17+
# 4. PR1 is merged.
18+
#
19+
# This is fine, at least the number of errors doesn't increase.
20+
# Additionally, because on step 4 above PR1 was merged, the base
21+
# branch itself got more linting errors, for this reason topic
22+
# branches (e.g. master or develop) should not break if linting
23+
# errors increase.
24+
if [[ ! -e ~/.local/BASE_COMMIT ]]; then
25+
exit 0
26+
fi
27+
28+
function compare_pylint_reports() {
29+
if [[ $# -ne 2 ]]; then
30+
echo "compare_pylint_reports was not properly called, it requires two arguments, $# given"
31+
exit 1
32+
fi
33+
34+
new=$1
35+
old=$2
36+
37+
if [[ ! -e "${new}" ]]; then
38+
echo "compare_pylint_reports was not properly called, new report ${new} is missing."
39+
exit 1
40+
fi
41+
42+
if [[ -e "${old}" ]]; then
43+
new_error_count=$(wc -l "${new}" | cut '-d ' -f1)
44+
previous_error_count=$(wc -l "${old}" | cut '-d ' -f1)
45+
46+
if [[ $new_error_count -gt $previous_error_count ]]; then
47+
diff ${old} ${new}
48+
49+
# DO NOT overwrite the old report in the cache, we want to keep the
50+
# version with the lower number of errors
51+
else
52+
# This PR fixed errors, move the new report over the old one to enforce
53+
# a new lower bound on the number of errors
54+
mv ${new} ${old}
55+
fi
56+
else
57+
# Save the report to compare on subsequent runs
58+
mv ${new} ${old}
59+
fi
60+
}
61+
62+
function compare_mypy_reports() {
63+
if [[ $# -ne 2 ]]; then
64+
echo "compare_mypy_reports was not properly called, it requires two arguments, $# given"
65+
exit 1
66+
fi
67+
68+
new=$1
69+
old=$2
70+
71+
if [[ ! -e "${new}" ]]; then
72+
echo "compare_mypy_reports was not properly called, new report ${new} is missing."
73+
exit 1
74+
fi
75+
76+
if [[ -e "${old}" ]]; then
77+
if ! ./.circleci/lint_report.py ${old} ${new}; then
78+
# DO NOT overwrite the old report in the cache, we want to keep the
79+
# version with the lower number of errors
80+
#
81+
# If this PR fixed errors, move the new report over the old one to
82+
# enforce a new lower bound on the number of errors
83+
mv ${new} ${old}
84+
fi
85+
else
86+
# Save the report to compare on subsequent runs
87+
mv ${new} ${old}
88+
fi
89+
}
90+
91+
CACHE_DIR="${HOME}/lint-cache"
92+
mkdir -p "${CACHE_DIR}"
93+
94+
old_report_pylint="${CACHE_DIR}/pylint"
95+
old_report_mypy="${CACHE_DIR}/mypy"
96+
new_report_pylint=$(mktemp)
97+
new_report_mypy=$(mktemp)
98+
99+
if [[ ! -z ${CIRCLECI} ]]; then
100+
JOBS=8
101+
else
102+
JOBS=0
103+
fi
104+
105+
pylint --jobs=${JOBS} \
106+
--load-plugins=tools.pylint.gevent_checker,tools.pylint.assert_checker \
107+
raiden/ tools/scenario-player/ > ${new_report_pylint} || true
108+
109+
mypy --config-file /dev/null --strict --disallow-subclassing-any \
110+
--disallow-any-expr --disallow-any-decorated --disallow-any-explicit \
111+
--disallow-any-generics raiden tools > ${new_report_mypy} || true
112+
113+
exit_code=0
114+
115+
if ! compare_pylint_reports "${new_report_pylint}" "${old_report_pylint}"; then
116+
exit_code=1
117+
fi
118+
119+
if ! compare_mypy_reports "${new_report_mypy}" "${old_report_mypy}"; then
120+
exit_code=1
121+
fi
122+
123+
exit ${exit_code}

.circleci/fetch_geth_parity_solc.sh

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,35 @@ if [[ ! -x ${GETH_PATH} ]]; then
1717
tar xzf geth.tar.gz
1818
cd geth*/
1919
install -m 755 geth ${GETH_PATH}
20+
21+
GETH_MD5_VAR="GETH_MD5_${OS_NAME}"
22+
if [[ ! -n ${!GETH_MD5_VAR} ]]; then
23+
COMPUTED_MD5=$(md5sum ${GETH_PATH} | cut '-d ' -f1)
24+
25+
if [[ ${COMPUTED_MD5} != ${!GETH_MD5_VAR} ]]; then
26+
exit 1;
27+
fi
28+
fi
2029
fi
21-
ln -sf ${GETH_PATH} ${LOCAL_BASE}/bin/geth
30+
ln -sfn ${GETH_PATH} ${LOCAL_BASE}/bin/geth
2231

2332
PARITY_PATH="${LOCAL_BASE}/bin/parity-${OS_NAME}-${PARITY_VERSION}"
2433
if [[ ! -x ${PARITY_PATH} ]]; then
2534
mkdir -p ${LOCAL_BASE}/bin
2635
PARITY_URL_VAR="PARITY_URL_${OS_NAME}"
2736
curl -L ${!PARITY_URL_VAR} > ${PARITY_PATH}
2837
chmod 775 ${PARITY_PATH}
38+
39+
PARITY_SHA256_VAR="PARITY_SHA256_${OS_NAME}"
40+
if [[ ! -n ${!PARITY_SHA256_VAR} ]]; then
41+
COMPUTED_SHA256=$(sha256sum ${PARITY_PATH} | cut '-d ' -f1)
42+
43+
if [[ ${COMPUTED_SHA256} != ${!PARITY_SHA256_VAR} ]]; then
44+
exit 1;
45+
fi
46+
fi
2947
fi
30-
ln -sf ${PARITY_PATH} ${LOCAL_BASE}/bin/parity
48+
ln -sfn ${PARITY_PATH} ${LOCAL_BASE}/bin/parity
3149

3250
# Only deal with solc for Linux since it's only used for testing
3351
if [[ ${OS_NAME} != "LINUX" ]]; then
@@ -41,4 +59,4 @@ if [[ ! -x ${SOLC_PATH} ]]; then
4159
curl -L ${!SOLC_URL_VAR} > ${SOLC_PATH}
4260
chmod 775 ${SOLC_PATH}
4361
fi
44-
ln -sf ${SOLC_PATH} ${LOCAL_BASE}/bin/solc
62+
ln -sfn ${SOLC_PATH} ${LOCAL_BASE}/bin/solc

.circleci/get_archive_tag.sh

100644100755
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,20 @@ set -ex
33

44
if [[ ! -z ${CIRCLE_TAG} ]]; then
55
export ARCHIVE_TAG=${CIRCLE_TAG}
6+
if [[ ${CIRCLE_TAG} = "*-rc*" ]]; then
7+
export RELEASE_TYPE="RC"
8+
else
9+
export RELEASE_TYPE="RELEASE"
10+
fi
11+
612
else
713
DATE=$(date +%Y-%m-%dT%H-%M-%S)
814
RAIDEN_VERSION=$(python setup.py --version)
915
export ARCHIVE_TAG="nightly-${DATE}-v${RAIDEN_VERSION}"
16+
export RELEASE_TYPE="NIGHTLY"
1017
fi
1118

1219
echo "export ARCHIVE_TAG=${ARCHIVE_TAG}" >> ${BASH_ENV}
20+
echo "export RELEASE_TYPE=${RELEASE_TYPE}" >> ${BASH_ENV}
1321

1422
set +ex

.circleci/lint_report.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env python3
2+
""" Utility to compare to report the number of increased errors in the same
3+
code.
4+
5+
The exit code of the tool will be 0 if the number of reported errors stayed the
6+
same *or decreased*. Otherwise it will be number of additional errors reported.
7+
8+
This utility assumes both reports are produced by the *same version of Mypy*,
9+
and that *the generated report has stable messages*, otherwise the errors
10+
results are not stable.
11+
"""
12+
import re
13+
import sys
14+
from collections import defaultdict
15+
from itertools import groupby
16+
from typing import Dict, Iterator, NamedTuple, Optional, Tuple
17+
18+
MYPY_LINE = re.compile(
19+
r"^"
20+
r"(?P<filename>([^:]|\\:)+):"
21+
r"((?P<linenum>([0-9]+)):)?"
22+
r"(?P<level>([^:]|\\:)+):"
23+
r"(?P<message>.+$)"
24+
)
25+
26+
27+
class FileErrorType(NamedTuple):
28+
filename: str
29+
errortype: str
30+
31+
32+
class Error(NamedTuple):
33+
filename: str
34+
linenum: str
35+
level: str
36+
message: str
37+
38+
39+
NewErrorCountPerFile = Dict[FileErrorType, int]
40+
UNKNOWN_REPORT_LINE = "Unrecognized line format"
41+
42+
43+
def compare_errors(error_old: Error, error_new: Error) -> int:
44+
# Errors for `filename` have been fixed according to the new report.
45+
if error_old.filename < error_new.filename:
46+
return -1
47+
48+
# Assuming stable output.
49+
message_old = (error_old.level, error_old.message)
50+
message_new = (error_new.level, error_new.message)
51+
52+
# The error `(level, message)` is fixed according to the new report
53+
if message_old < message_new:
54+
return -1
55+
56+
if message_old == message_new:
57+
return 0
58+
59+
# Do not compare line numbers. If the error moved around it does not
60+
# matter, only new and fixed bugs.
61+
62+
return 1
63+
64+
65+
def next_error(f: Iterator[Error]) -> Optional[Error]:
66+
try:
67+
return next(f)
68+
except StopIteration:
69+
return None
70+
71+
72+
def get_errors(previous_report: str) -> Iterator[Error]:
73+
with open(previous_report, "r") as file:
74+
for line in file:
75+
match = MYPY_LINE.match(line)
76+
assert match, UNKNOWN_REPORT_LINE
77+
78+
error = Error(
79+
filename=match["filename"],
80+
linenum=match["linenum"],
81+
level=match["level"],
82+
message=match["message"],
83+
)
84+
yield error
85+
86+
87+
def sort_by_filename_level_error(error: Error) -> Tuple:
88+
return error.filename, error.level, error.message
89+
90+
91+
def compare_reports(previous_report: str, new_report: str) -> Tuple[NewErrorCountPerFile, int]:
92+
previous_errors_unsorted = get_errors(previous_report)
93+
new_errors_unsorted = get_errors(new_report)
94+
95+
previous_errors = sorted(previous_errors_unsorted, key=sort_by_filename_level_error)
96+
new_errors = sorted(new_errors_unsorted, key=sort_by_filename_level_error)
97+
98+
previous_errors_it = iter(previous_errors)
99+
new_errors_it = iter(new_errors)
100+
101+
new_errors_count = 0
102+
error_count: NewErrorCountPerFile = defaultdict(int)
103+
104+
previous_error = next_error(previous_errors_it)
105+
new_error = next_error(new_errors_it)
106+
107+
while previous_error is not None and new_error is not None:
108+
compare = compare_errors(previous_error, new_error)
109+
110+
# The new report has a new error
111+
if compare > 0:
112+
new_errors_count += 1
113+
error_count[FileErrorType(new_error.filename, new_error.message)] += 1
114+
115+
if compare < 0:
116+
previous_error = next_error(previous_errors_it)
117+
elif compare == 0:
118+
previous_error = next_error(previous_errors_it)
119+
new_error = next_error(new_errors_it)
120+
else:
121+
new_error = next_error(new_errors_it)
122+
123+
# Extra lines in the new report are new errors
124+
while new_error is not None:
125+
new_errors_count += 1
126+
error_count[FileErrorType(new_error.filename, new_error.message)] += 1
127+
128+
new_error = next_error(new_errors_it)
129+
130+
return error_count, new_errors_count
131+
132+
133+
def print_changes(report: NewErrorCountPerFile) -> None:
134+
error_types_grouped_by_filename = groupby(sorted(report), key=lambda k: k.filename)
135+
136+
for filename, error_types_it in error_types_grouped_by_filename:
137+
error_types = list(error_types_it)
138+
total_errors_for_file = sum(report[error] for error in error_types)
139+
140+
print(f"{filename} :: +{total_errors_for_file}")
141+
for error in error_types:
142+
print(f" +{report[error]} :: {error.errortype}")
143+
print()
144+
print()
145+
146+
147+
def main() -> None:
148+
import argparse
149+
150+
parser = argparse.ArgumentParser()
151+
parser.add_argument("previous_report")
152+
parser.add_argument("new_report")
153+
args = parser.parse_args()
154+
155+
report, changes = compare_reports(args.previous_report, args.new_report)
156+
157+
if changes > 0:
158+
print_changes(report)
159+
sys.exit(changes)
160+
161+
162+
if __name__ == "__main__":
163+
main()

0 commit comments

Comments
 (0)