From fd8a88f2b735dd31d1b122a7d03e03ccc09d748c Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 7 Jul 2022 15:43:55 -0700 Subject: [PATCH 1/8] Add CI checks for mypy and pylint - Configuration copied from cirq. --- .github/workflows/mypy.yml | 19 +++++++++ .github/workflows/pylint.yml | 19 +++++++++ dev_tools/.pylintrc | 77 ++++++++++++++++++++++++++++++++++++ dev_tools/mypy | 22 +++++++++++ dev_tools/mypy.ini | 27 +++++++++++++ dev_tools/pylint | 16 ++++++++ requirements.txt | 7 ++++ 7 files changed, 187 insertions(+) create mode 100644 .github/workflows/mypy.yml create mode 100644 .github/workflows/pylint.yml create mode 100644 dev_tools/.pylintrc create mode 100755 dev_tools/mypy create mode 100644 dev_tools/mypy.ini create mode 100755 dev_tools/pylint diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml new file mode 100644 index 00000000..5280a6c1 --- /dev/null +++ b/.github/workflows/mypy.yml @@ -0,0 +1,19 @@ +name: Type Check + +on: [push, pull_request] + +jobs: + mypy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v1 + with: + python-version: '3.8' + architecture: 'x64' + - name: Install mypy + run: | + python -m pip install --upgrade pip + pip install mypy + - name: Type check + run: dev_tools/mypy diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 00000000..d03ac5f1 --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,19 @@ +name: Pylint + +on: [push, pull_request] + +jobs: + mypy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v1 + with: + python-version: '3.8' + architecture: 'x64' + - name: Install Pylint + run: | + python -m pip install --upgrade pip + pip install pylint + - name: Pylint check + run: dev_tools/pylint diff --git a/dev_tools/.pylintrc b/dev_tools/.pylintrc new file mode 100644 index 00000000..436abe88 --- /dev/null +++ b/dev_tools/.pylintrc @@ -0,0 +1,77 @@ +[MASTER] +load-plugins=pylint.extensions.docstyle,pylint.extensions.docparams,pylint_copyright_checker +max-line-length=100 +disable=all +#ignore-paths=cirq-google/cirq_google/cloud/.* +ignore-patterns=.*_pb2\.py +output-format=colorized +score=no +reports=no +enable= + anomalous-backslash-in-string, + assert-on-tuple, + bad-indentation, + bad-option-value, + bad-reversed-sequence, + bad-super-call, + consider-merging-isinstance, + continue-in-finally, + dangerous-default-value, + docstyle, + duplicate-argument-name, + expression-not-assigned, + f-string-without-interpolation + function-redefined, + inconsistent-mro, + init-is-generator, + line-too-long, + lost-exception, + missing-kwoa, + missing-param-doc, + missing-raises-doc, + mixed-indentation, + mixed-line-endings, + no-value-for-parameter, + nonexistent-operator, + not-in-loop, + pointless-statement, + redefined-builtin, + relative-import, + return-arg-in-generator, + return-in-init, + return-outside-function, + simplifiable-if-statement, + singleton-comparison, + syntax-error, + too-many-function-args, + trailing-whitespace, + undefined-variable, + unexpected-keyword-arg, + unhashable-dict-key, + unnecessary-pass, + unreachable, + unrecognized-inline-option, + unused-import, + unnecessary-semicolon, + unused-variable, + unused-wildcard-import, + wildcard-import, + wrong-or-nonexistent-copyright-notice, + wrong-import-order, + wrong-import-position, + yield-outside-function + +# Ignore long lines containing urls or pylint directives. +ignore-long-lines=^(.*#\w*pylint: disable.*|\s*(# )?[<\[\(]?https?://\S+[>\]\)]?)$ + +[TYPECHECK] + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=numpy.* + + +#[IMPORTS] +# Force import order to recognize a module as part of a third party library. +#known-third-party=cirq,cirq_google,cirq_aqt,cirq_ionq diff --git a/dev_tools/mypy b/dev_tools/mypy new file mode 100755 index 00000000..24b3eba7 --- /dev/null +++ b/dev_tools/mypy @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +################################################################################ +# Runs mypy on the repository using a preconfigured mypy.ini file. +# +# Usage: +# check/mypy [--flags] +################################################################################ + +# Get the working directory to the repo root. +cd "$(dirname "${BASH_SOURCE[0]}")" +cd "$(git rev-parse --show-toplevel)" + + +CIRQ_PACKAGES=$(env PYTHONPATH=. python dev_tools/modules.py list --mode package-path) + +echo -e -n "\033[31m" +mypy --config-file=dev_tools/mypy.ini "$@" . +result=$? +echo -e -n "\033[0m" + +exit ${result} diff --git a/dev_tools/mypy.ini b/dev_tools/mypy.ini new file mode 100644 index 00000000..6df170c4 --- /dev/null +++ b/dev_tools/mypy.ini @@ -0,0 +1,27 @@ +[mypy] +show_error_codes = true + +[mypy-__main__] +follow_imports = silent +ignore_missing_imports = true + +# 3rd-party libs for which we don't have stubs +[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*] +follow_imports = silent +ignore_missing_imports = true + +# There was no type information before numpy 1.20, so there are numpy mypy issues in the codebase +[mypy-numpy.*] +follow_imports = skip +follow_imports_for_stubs = true + +# Treat symbols imported from Google's protobuf library as type Any. +# This supresses errors due to attributes not known to typeshed, +# e.g. Descriptor._options. +[mypy-google.protobuf.*] +follow_imports = skip +follow_imports_for_stubs = true + +# ruamel is a downstream dependency of cirq-rigetti through pyquil. +[mypy-ruamel.*] +ignore_missing_imports = true diff --git a/dev_tools/pylint b/dev_tools/pylint new file mode 100755 index 00000000..65e39b91 --- /dev/null +++ b/dev_tools/pylint @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +################################################################################ +# Runs pylint on the repository using a preconfigured .pylintrc file. +# +# Usage: +# check/pylint [--flags for pylint] +################################################################################ + +# Get the working directory to the repo root. +cd "$(dirname "${BASH_SOURCE[0]}")" +cd "$(git rev-parse --show-toplevel)" +CIRQ_MODULES=$(env PYTHONPATH=. python dev_tools/modules.py list --mode package-path) + +# Add dev_tools to $PYTHONPATH so that pylint can find custom checkers +env PYTHONPATH=dev_tools pylint --jobs=0 --rcfile=dev_tools/.pylintrc "$@" . diff --git a/requirements.txt b/requirements.txt index 3a379bfa..5f38b4b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,5 +4,12 @@ cirq-google>=0.14.0 seaborn sphinx + +# dev tools ipython black +mypy +pylint +pytest +pytest-cov +coverage<=6.2 From 0ba21053d20bf8fd7979a0b171b9ae5cb0ec9e3d Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 7 Jul 2022 15:45:38 -0700 Subject: [PATCH 2/8] Try to fix pylint --- .github/workflows/pylint.yml | 2 +- dev_tools/pylint | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index d03ac5f1..c59b6d03 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -3,7 +3,7 @@ name: Pylint on: [push, pull_request] jobs: - mypy: + pylint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/dev_tools/pylint b/dev_tools/pylint index 65e39b91..3d88f809 100755 --- a/dev_tools/pylint +++ b/dev_tools/pylint @@ -10,7 +10,6 @@ # Get the working directory to the repo root. cd "$(dirname "${BASH_SOURCE[0]}")" cd "$(git rev-parse --show-toplevel)" -CIRQ_MODULES=$(env PYTHONPATH=. python dev_tools/modules.py list --mode package-path) # Add dev_tools to $PYTHONPATH so that pylint can find custom checkers env PYTHONPATH=dev_tools pylint --jobs=0 --rcfile=dev_tools/.pylintrc "$@" . From d71936dc249d8ba9ae980b1f19eb7b3208d73486 Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 7 Jul 2022 15:49:25 -0700 Subject: [PATCH 3/8] Try again. --- dev_tools/.pylintrc | 4 ---- dev_tools/mypy | 2 -- dev_tools/mypy.ini | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/dev_tools/.pylintrc b/dev_tools/.pylintrc index 436abe88..aeb6b8a8 100644 --- a/dev_tools/.pylintrc +++ b/dev_tools/.pylintrc @@ -20,7 +20,6 @@ enable= docstyle, duplicate-argument-name, expression-not-assigned, - f-string-without-interpolation function-redefined, inconsistent-mro, init-is-generator, @@ -29,14 +28,12 @@ enable= missing-kwoa, missing-param-doc, missing-raises-doc, - mixed-indentation, mixed-line-endings, no-value-for-parameter, nonexistent-operator, not-in-loop, pointless-statement, redefined-builtin, - relative-import, return-arg-in-generator, return-in-init, return-outside-function, @@ -56,7 +53,6 @@ enable= unused-variable, unused-wildcard-import, wildcard-import, - wrong-or-nonexistent-copyright-notice, wrong-import-order, wrong-import-position, yield-outside-function diff --git a/dev_tools/mypy b/dev_tools/mypy index 24b3eba7..b804ed14 100755 --- a/dev_tools/mypy +++ b/dev_tools/mypy @@ -12,8 +12,6 @@ cd "$(dirname "${BASH_SOURCE[0]}")" cd "$(git rev-parse --show-toplevel)" -CIRQ_PACKAGES=$(env PYTHONPATH=. python dev_tools/modules.py list --mode package-path) - echo -e -n "\033[31m" mypy --config-file=dev_tools/mypy.ini "$@" . result=$? diff --git a/dev_tools/mypy.ini b/dev_tools/mypy.ini index 6df170c4..78a4f3af 100644 --- a/dev_tools/mypy.ini +++ b/dev_tools/mypy.ini @@ -6,7 +6,7 @@ follow_imports = silent ignore_missing_imports = true # 3rd-party libs for which we don't have stubs -[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*] +[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*,cirq.*] follow_imports = silent ignore_missing_imports = true From 284eafd4a52738b84cf12b31d8fec8156e734609 Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 7 Jul 2022 15:52:10 -0700 Subject: [PATCH 4/8] Fix some stubs. --- dev_tools/mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/mypy.ini b/dev_tools/mypy.ini index 78a4f3af..b3c7eed4 100644 --- a/dev_tools/mypy.ini +++ b/dev_tools/mypy.ini @@ -6,7 +6,7 @@ follow_imports = silent ignore_missing_imports = true # 3rd-party libs for which we don't have stubs -[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*,cirq.*] +[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*,cirq.*,flask.*,numpy.*,cirq_google.*] follow_imports = silent ignore_missing_imports = true From e822f52a50cc2e16b240377e40a9cb1511a66b3a Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Thu, 7 Jul 2022 15:53:33 -0700 Subject: [PATCH 5/8] Allow mypy to succeed temporarily. --- .github/workflows/mypy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 5280a6c1..b6a2f6ec 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -16,4 +16,4 @@ jobs: python -m pip install --upgrade pip pip install mypy - name: Type check - run: dev_tools/mypy + run: dev_tools/mypy || true From b79135d4d946f83dd057e9189c89fe65faa66f89 Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Wed, 20 Jul 2022 10:01:04 -0700 Subject: [PATCH 6/8] Slim down requirements. --- requirements.txt | 4 +-- unitary/__init__.py | 4 --- unitary/documentation_utils.py | 53 ---------------------------------- 3 files changed, 2 insertions(+), 59 deletions(-) delete mode 100644 unitary/documentation_utils.py diff --git a/requirements.txt b/requirements.txt index 5f38b4b4..047c3bc8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,8 @@ cirq-core>=0.14.0 cirq-google>=0.14.0 # When changing Cirq requirements be sure to update dev_tools/write-ci-requirements.py -seaborn -sphinx +numpy +sympy # dev tools ipython diff --git a/unitary/__init__.py b/unitary/__init__.py index 3e0d2855..a6ce2123 100644 --- a/unitary/__init__.py +++ b/unitary/__init__.py @@ -20,7 +20,3 @@ get_sampler_by_name, execute_in_queue, ) - -from unitary.documentation_utils import ( - display_markdown_docstring, -) diff --git a/unitary/documentation_utils.py b/unitary/documentation_utils.py deleted file mode 100644 index 313a1e7e..00000000 --- a/unitary/documentation_utils.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2020 Google -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# 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. - -import inspect -import os -import re -import tarfile -import urllib.request - -from sphinx.ext.napoleon import Config, GoogleDocstring - - -class GoogleDocstringToMarkdown(GoogleDocstring): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.markdown_lines = [] - - def _parse_attributes_section(self, section): - lines = ['#### Attributes'] - for _name, _type, _desc in self._consume_fields(): - desc = ' '.join(_desc) - lines += [f' - `{_name}`: {desc}'] - - lines += [''] - return lines - - def _parse_see_also_section(self, section): - lines = self._consume_to_next_section() - lines = [line.strip() for line in lines] - return ['#### See Also', ' '.join(lines), ''] - - -def display_markdown_docstring(cls): - config = Config() - gds = GoogleDocstringToMarkdown(inspect.cleandoc(cls.__doc__), - config=config, what='class') - gds_lines = [f'### {cls.__name__}'] + gds.lines() - gds_lines = [re.sub(r':py:func:`(\w+)`', r'`\1`', line) - for line in gds_lines] - - from IPython.display import Markdown - return Markdown('\n'.join(gds_lines)) From 3fa180c88f62879dacc41e811732742fb64200ba Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Wed, 20 Jul 2022 10:03:09 -0700 Subject: [PATCH 7/8] Slim down mypy deps. --- dev_tools/mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/mypy.ini b/dev_tools/mypy.ini index b3c7eed4..83831e15 100644 --- a/dev_tools/mypy.ini +++ b/dev_tools/mypy.ini @@ -6,7 +6,7 @@ follow_imports = silent ignore_missing_imports = true # 3rd-party libs for which we don't have stubs -[mypy-apiclient.*,freezegun.*,matplotlib.*,mpl_toolkits,multiprocessing.dummy,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,sortedcontainers.*,setuptools.*,pylatex.*,networkx.*,qiskit.*,pypandoc.*,ply.*,_pytest.*,google.api.*,google.api_core.*,grpc.*,google.auth.*,google.oauth2.*,google.protobuf.text_format.*,quimb.*,pyquil.*,google.cloud.*,filelock.*,codeowners.*,tqdm.*,importlib_metadata.*,google.colab.*,IPython.*,astroid.*,pylint.*,cirq.*,flask.*,numpy.*,cirq_google.*] +[mypy-apiclient.*,matplotlib.*,mpl_toolkits,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,setuptools.*,networkx.*,_pytest.*,codeowners.*,pylint.*,cirq.*,flask.*,numpy.*,cirq_google.*] follow_imports = silent ignore_missing_imports = true From a6114a69016eb862ab437a087bc78d7457c3ed34 Mon Sep 17 00:00:00 2001 From: Doug Strain Date: Wed, 20 Jul 2022 10:10:27 -0700 Subject: [PATCH 8/8] Adjust numpy mypy --- dev_tools/mypy.ini | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/dev_tools/mypy.ini b/dev_tools/mypy.ini index 83831e15..46349a2e 100644 --- a/dev_tools/mypy.ini +++ b/dev_tools/mypy.ini @@ -6,7 +6,7 @@ follow_imports = silent ignore_missing_imports = true # 3rd-party libs for which we don't have stubs -[mypy-apiclient.*,matplotlib.*,mpl_toolkits,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,setuptools.*,networkx.*,_pytest.*,codeowners.*,pylint.*,cirq.*,flask.*,numpy.*,cirq_google.*] +[mypy-apiclient.*,matplotlib.*,mpl_toolkits,oauth2client.*,pandas.*,proto.*,pytest.*,scipy.*,setuptools.*,networkx.*,_pytest.*,codeowners.*,pylint.*,numpy.*,cirq.*,flask.*,numpy.*,cirq_google.*] follow_imports = silent ignore_missing_imports = true @@ -14,14 +14,3 @@ ignore_missing_imports = true [mypy-numpy.*] follow_imports = skip follow_imports_for_stubs = true - -# Treat symbols imported from Google's protobuf library as type Any. -# This supresses errors due to attributes not known to typeshed, -# e.g. Descriptor._options. -[mypy-google.protobuf.*] -follow_imports = skip -follow_imports_for_stubs = true - -# ruamel is a downstream dependency of cirq-rigetti through pyquil. -[mypy-ruamel.*] -ignore_missing_imports = true