mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8144 from ethereum/pylint
CircleCI: Adds pylint test for all python files in scripts/ directory.
This commit is contained in:
commit
836938c105
@ -257,6 +257,22 @@ jobs:
|
|||||||
name: Check for C++ coding style
|
name: Check for C++ coding style
|
||||||
command: ./scripts/check_style.sh
|
command: ./scripts/check_style.sh
|
||||||
|
|
||||||
|
chk_pylint:
|
||||||
|
docker:
|
||||||
|
- image: buildpack-deps:eoan
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Install pip
|
||||||
|
command: apt -q update && apt install -y python3-pip
|
||||||
|
- run:
|
||||||
|
name: Install pylint
|
||||||
|
command: python3 -m pip install pylint z3-solver
|
||||||
|
# also z3-solver to make sure pylint knows about this module
|
||||||
|
- run:
|
||||||
|
name: Linting Python Scripts
|
||||||
|
command: ./scripts/pylint_all.py
|
||||||
|
|
||||||
chk_buglist:
|
chk_buglist:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node
|
- image: circleci/node
|
||||||
@ -718,6 +734,7 @@ workflows:
|
|||||||
# DISABLED FOR 0.6.0 - chk_docs_examples: *workflow_trigger_on_tags
|
# DISABLED FOR 0.6.0 - chk_docs_examples: *workflow_trigger_on_tags
|
||||||
- chk_buglist: *workflow_trigger_on_tags
|
- chk_buglist: *workflow_trigger_on_tags
|
||||||
- chk_proofs: *workflow_trigger_on_tags
|
- chk_proofs: *workflow_trigger_on_tags
|
||||||
|
- chk_pylint: *workflow_trigger_on_tags
|
||||||
|
|
||||||
# build-only
|
# build-only
|
||||||
- b_docs: *workflow_trigger_on_tags
|
- b_docs: *workflow_trigger_on_tags
|
||||||
|
@ -17,6 +17,8 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from pygments_lexer_solidity import SolidityLexer
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
@ -24,7 +26,6 @@ import re
|
|||||||
def setup(sphinx):
|
def setup(sphinx):
|
||||||
thisdir = os.path.dirname(os.path.realpath(__file__))
|
thisdir = os.path.dirname(os.path.realpath(__file__))
|
||||||
sys.path.insert(0, thisdir + '/utils')
|
sys.path.insert(0, thisdir + '/utils')
|
||||||
from pygments_lexer_solidity import SolidityLexer
|
|
||||||
sphinx.add_lexer('Solidity', SolidityLexer())
|
sphinx.add_lexer('Solidity', SolidityLexer())
|
||||||
|
|
||||||
sphinx.add_stylesheet('css/custom.css')
|
sphinx.add_stylesheet('css/custom.css')
|
||||||
|
@ -33,7 +33,8 @@ for optimize in [False, True]:
|
|||||||
for contractName in sorted(result['contracts'][filename].keys()):
|
for contractName in sorted(result['contracts'][filename].keys()):
|
||||||
contractData = result['contracts'][filename][contractName]
|
contractData = result['contracts'][filename][contractName]
|
||||||
if 'evm' in contractData and 'bytecode' in contractData['evm']:
|
if 'evm' in contractData and 'bytecode' in contractData['evm']:
|
||||||
REPORT_FILE.write(filename + ':' + contractName + ' ' + contractData['evm']['bytecode']['object'] + '\n')
|
REPORT_FILE.write(filename + ':' + contractName + ' ' +
|
||||||
|
contractData['evm']['bytecode']['object'] + '\n')
|
||||||
else:
|
else:
|
||||||
REPORT_FILE.write(filename + ':' + contractName + ' NO BYTECODE\n')
|
REPORT_FILE.write(filename + ':' + contractName + ' NO BYTECODE\n')
|
||||||
REPORT_FILE.write(filename + ':' + contractName + ' ' + contractData['metadata'] + '\n')
|
REPORT_FILE.write(filename + ':' + contractName + ' ' + contractData['metadata'] + '\n')
|
||||||
|
@ -49,7 +49,9 @@ def readDependencies(fname):
|
|||||||
for line in o.stdout:
|
for line in o.stdout:
|
||||||
if line[0] == '\t':
|
if line[0] == '\t':
|
||||||
library = line.split(' ', 1)[0][1:]
|
library = line.split(' ', 1)[0][1:]
|
||||||
if library.startswith("/usr/local/lib") or library.startswith("/usr/local/opt") or library.startswith("/Users/"):
|
if (library.startswith("/usr/local/lib") or
|
||||||
|
library.startswith("/usr/local/opt") or
|
||||||
|
library.startswith("/Users/")):
|
||||||
if (os.path.basename(library) != os.path.basename(fname)):
|
if (os.path.basename(library) != os.path.basename(fname)):
|
||||||
command = "install_name_tool -change " + \
|
command = "install_name_tool -change " + \
|
||||||
library + " @executable_path/./" + \
|
library + " @executable_path/./" + \
|
||||||
|
56
scripts/pylint_all.py
Executable file
56
scripts/pylint_all.py
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Performs pylint on all python files in the project repo's test directory recursively.
|
||||||
|
|
||||||
|
This script is meant to be run from the CI but can also be easily in local dev environment,
|
||||||
|
where you can optionally pass `-d` as command line argument to let this script abort on first error.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from os import path, walk, system
|
||||||
|
from sys import argv, exit as brexit
|
||||||
|
|
||||||
|
PROJECT_ROOT = path.dirname(path.realpath(__file__))
|
||||||
|
PYLINT_RCFILE = "{}/pylintrc".format(PROJECT_ROOT)
|
||||||
|
|
||||||
|
SGR_INFO = "\033[1;32m"
|
||||||
|
SGR_CLEAR = "\033[0m"
|
||||||
|
|
||||||
|
def pylint_all_filenames(dev_mode, rootdirs):
|
||||||
|
""" Performs pylint on all python files within given root directory (recursively). """
|
||||||
|
filenames = []
|
||||||
|
for rootdir in rootdirs:
|
||||||
|
for rootpath, _, filenames_w in walk(rootdir):
|
||||||
|
for filename in filenames_w:
|
||||||
|
if filename.endswith('.py'):
|
||||||
|
filenames.append(path.join(rootpath, filename))
|
||||||
|
|
||||||
|
checked_count = 0
|
||||||
|
failed = []
|
||||||
|
for filename in filenames:
|
||||||
|
checked_count += 1
|
||||||
|
cmdline = "pylint --rcfile=\"{}\" \"{}\"".format(PYLINT_RCFILE, filename)
|
||||||
|
print("{}[{}/{}] Running pylint on file: {}{}".format(SGR_INFO, checked_count, len(filenames),
|
||||||
|
filename, SGR_CLEAR))
|
||||||
|
exit_code = system(cmdline)
|
||||||
|
if exit_code != 0:
|
||||||
|
if dev_mode:
|
||||||
|
return 1, checked_count
|
||||||
|
else:
|
||||||
|
failed.append(filename)
|
||||||
|
|
||||||
|
return len(failed), len(filenames)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""" Collects all python script root dirs and runs pylint on them. """
|
||||||
|
dev_mode = len(argv) == 2 and argv[1] == "-d"
|
||||||
|
failed_count, total_count = pylint_all_filenames(dev_mode, [
|
||||||
|
path.abspath(path.dirname(__file__) + "/../scripts"),
|
||||||
|
path.abspath(path.dirname(__file__) + "/../test")])
|
||||||
|
if failed_count != 0:
|
||||||
|
brexit("pylint failed on {}/{} files.".format(failed_count, total_count))
|
||||||
|
else:
|
||||||
|
print("Successfully tested {} files.".format(total_count))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
74
scripts/pylintrc
Normal file
74
scripts/pylintrc
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# vim:et:ts=4
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
|
||||||
|
# Disable the message, report, category or checker with the given id(s). You
|
||||||
|
# can either give multiple identifiers separated by comma (,) or put this
|
||||||
|
# option multiple times (only on the command line, not in the configuration
|
||||||
|
# file where it should appear only once).You can also use "--disable=all" to
|
||||||
|
# disable everything first and then re-enable specific checks. For example, if
|
||||||
|
# you want to run only the similarities checker, you can use "--disable=all
|
||||||
|
# --enable=similarities". If you want to run only the classes checker, but have
|
||||||
|
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||||
|
# --disable=W"
|
||||||
|
|
||||||
|
# ATTENTION: This list should be extended with care, consider using NOLINT comments inside your
|
||||||
|
# python files instead, as the goal is actually to reduce the list of globally disabled checks.
|
||||||
|
#
|
||||||
|
# TODO: What could be eliminated in future PRs: bad-continuation, invalid-name, redefined-builtin,
|
||||||
|
# undefined-variable, unused-*, useless-object-inheritance.
|
||||||
|
disable=
|
||||||
|
bad-continuation,
|
||||||
|
bad-indentation,
|
||||||
|
bad-whitespace,
|
||||||
|
consider-using-sys-exit,
|
||||||
|
invalid-name,
|
||||||
|
missing-docstring,
|
||||||
|
mixed-indentation,
|
||||||
|
no-else-return,
|
||||||
|
no-self-use,
|
||||||
|
pointless-string-statement,
|
||||||
|
redefined-builtin,
|
||||||
|
redefined-outer-name,
|
||||||
|
singleton-comparison,
|
||||||
|
superfluous-parens,
|
||||||
|
too-few-public-methods,
|
||||||
|
trailing-newlines,
|
||||||
|
undefined-variable,
|
||||||
|
ungrouped-imports,
|
||||||
|
unnecessary-semicolon,
|
||||||
|
unused-import,
|
||||||
|
unused-variable,
|
||||||
|
unused-wildcard-import,
|
||||||
|
useless-object-inheritance,
|
||||||
|
wildcard-import
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
|
||||||
|
# Good variable names which should always be accepted, separated by a comma
|
||||||
|
# added: f, h, x, a, b, p
|
||||||
|
good-names=
|
||||||
|
Run,
|
||||||
|
_,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
ex,
|
||||||
|
f,
|
||||||
|
f,
|
||||||
|
h,
|
||||||
|
h,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
k,
|
||||||
|
l,
|
||||||
|
m,
|
||||||
|
n,
|
||||||
|
p,
|
||||||
|
x
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
|
||||||
|
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||||
|
expected-line-ending-format=LF
|
||||||
|
|
||||||
|
# Maximum number of characters on a single line.
|
||||||
|
max-line-length=110
|
@ -27,8 +27,8 @@ def extractSourceName(line):
|
|||||||
# writes the following source into a file named sourceName
|
# writes the following source into a file named sourceName
|
||||||
def writeSourceToFile(lines):
|
def writeSourceToFile(lines):
|
||||||
filePath, srcName = extractSourceName(lines[0])
|
filePath, srcName = extractSourceName(lines[0])
|
||||||
# print "sourceName is", srcName
|
# print("sourceName is ", srcName)
|
||||||
# print "filePath is", filePath
|
# print("filePath is", filePath)
|
||||||
if filePath != False:
|
if filePath != False:
|
||||||
os.system("mkdir -p " + filePath)
|
os.system("mkdir -p " + filePath)
|
||||||
f = open(srcName, mode='a+', encoding='utf8')
|
f = open(srcName, mode='a+', encoding='utf8')
|
||||||
|
Loading…
Reference in New Issue
Block a user