From 05b61a5199dd69e33011ed0e677d9d43a77c01a4 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Thu, 20 Dec 2018 12:10:53 -0800 Subject: [PATCH] Use Pylint to lint gRPC Python examples --- .pylintrc-examples | 100 ++++++++++++++++++ .../helloworld/greeter_client_with_options.py | 2 +- tools/distrib/pylint_code.sh | 6 ++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 .pylintrc-examples diff --git a/.pylintrc-examples b/.pylintrc-examples new file mode 100644 index 00000000000..9480d6ea56a --- /dev/null +++ b/.pylintrc-examples @@ -0,0 +1,100 @@ +[MASTER] +ignore= + src/python/grpcio/grpc/beta, + src/python/grpcio/grpc/framework, + src/python/grpcio/grpc/framework/common, + src/python/grpcio/grpc/framework/foundation, + src/python/grpcio/grpc/framework/interfaces, + +[VARIABLES] + +# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection +# not include "unused_" and "ignored_" by default? +dummy-variables-rgx=^ignored_|^unused_ + +[DESIGN] + +# NOTE(nathaniel): Not particularly attached to this value; it just seems to +# be what works for us at the moment (excepting the dead-code-walking Beta +# API). +max-args=6 + +[MISCELLANEOUS] + +# NOTE(nathaniel): We are big fans of "TODO(): " and +# "NOTE(): ". We do not allow "TODO:", +# "TODO():", "FIXME:", or anything else. +notes=FIXME,XXX + +[MESSAGES CONTROL] + +disable= + # -- START OF EXAMPLE-SPECIFIC SUPPRESSIONS -- + no-self-use, + unused-argument, + unused-variable, + # -- END OF EXAMPLE-SPECIFIC SUPPRESSIONS -- + + # TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279): + # Enable cyclic-import after a 1.7-or-later pylint release that + # recognizes our disable=cyclic-import suppressions. + cyclic-import, + # TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the + # Beta API is removed. + duplicate-code, + # TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to + # understand enum and concurrent.futures; look into this later with the + # latest pylint version. + import-error, + # TODO(https://github.com/grpc/grpc/issues/261): Enable this one. + # Should take a little configuration but not much. + invalid-name, + # TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to + # work for now? Try with a later pylint? + locally-disabled, + # NOTE(nathaniel): What even is this? *Enabling* an inspection results + # in a warning? How does that encourage more analysis and coverage? + locally-enabled, + # NOTE(nathaniel): We don't write doc strings for most private code + # elements. + missing-docstring, + # NOTE(nathaniel): In numeric comparisons it is better to have the + # lesser (or lesser-or-equal-to) quantity on the left when the + # expression is true than it is to worry about which is an identifier + # and which a literal value. + misplaced-comparison-constant, + # NOTE(nathaniel): Our completely abstract interface classes don't have + # constructors. + no-init, + # TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play + # nicely with some of our code being implemented in Cython. Maybe in a + # later version? + no-name-in-module, + # TODO(https://github.com/grpc/grpc/issues/261): Suppress these where + # the odd shape of the authentication portion of the API forces them on + # us and enable everywhere else. + protected-access, + # NOTE(nathaniel): Pylint and I will probably never agree on this. + too-few-public-methods, + # NOTE(nathaniel): Pylint and I wil probably never agree on this for + # private classes. For public classes maybe? + too-many-instance-attributes, + # NOTE(nathaniel): Some of our modules have a lot of lines... of + # specification and documentation. Maybe if this were + # lines-of-code-based we would use it. + too-many-lines, + # TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have + # this one if we extracted just a few more helper functions... + too-many-nested-blocks, + # TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary + # super-init requirement for abstract class implementations for now. + super-init-not-called, + # NOTE(nathaniel): A single statement that always returns program + # control is better than two statements the first of which sometimes + # returns program control and the second of which always returns + # program control. Probably generally, but definitely in the cases of + # if:/else: and for:/else:. + useless-else-on-loop, + no-else-return, + # NOTE(lidiz): Python 3 make object inheritance default, but not PY2 + useless-object-inheritance, diff --git a/examples/python/helloworld/greeter_client_with_options.py b/examples/python/helloworld/greeter_client_with_options.py index d15871b5195..e9ab5508ddd 100644 --- a/examples/python/helloworld/greeter_client_with_options.py +++ b/examples/python/helloworld/greeter_client_with_options.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""The Python implementation of the GRPC helloworld.Greeter client with channel options and call timeout parameters.""" +"""gRPC Python helloworld.Greeter client with channel options and call timeout parameters.""" from __future__ import print_function import logging diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh index 00507775031..abb37dde0ed 100755 --- a/tools/distrib/pylint_code.sh +++ b/tools/distrib/pylint_code.sh @@ -48,4 +48,10 @@ for dir in "${TEST_DIRS[@]}"; do $PYTHON -m pylint --rcfile=.pylintrc-tests -rn "$dir" || EXIT=1 done +find examples/python \ + -iname "*.py" \ + -not -name "*_pb2.py" \ + -not -name "*_pb2_grpc.py" \ + | xargs $PYTHON -m pylint --rcfile=.pylintrc-examples -rn + exit $EXIT