Repository: quantumlib/Cirq

Issue:
check/pylint sometimes doesn't check imports
An unused import (`Optional`) passed CI here: https://github.com/quantumlib/Cirq/blame/master/cirq/ops/pauli_gates.py#L15

Now I'm getting an error for that on Travis: https://travis-ci.com/quantumlib/Cirq/jobs/225990740#L253

When I run pylint locally, I don't catch this or other import errors.  This has happened during my last few PRs: https://travis-ci.com/quantumlib/Cirq/jobs/225990740#L251

I updated my local pylint to pylint==2.3.1, astroid==2.1.0 and still don't get the errors that Travis shows.

Can anyone else reproduce this?


Discussion:
Could it be that the errors have nothing to do with the `unused import`? What you linked has 
```
cirq/optimizers/eject_phased_paulis_test.py:42:0: C0301: Line too long (83/80) (line-too-long)

cirq/optimizers/eject_phased_paulis_test.py:18:0: C0411: third party import "import numpy as np" should be placed before "import sympy" (wrong-import-order)
```
Alongside the unused import error.
The same thing happened in #1963 (last commit on Apr 15).  I got an unused import error on Travis but no errors locally.
I just ran your `cduck:eject-pauli` branch locally on my machine and i received lots of unused imports.
```
vtomole@vtomole:~/Cirq$ check/pylint
************* Module cirq.neutral_atoms.neutral_atom_devices
cirq/neutral_atoms/neutral_atom_devices.py:18:0: W0611: Unused DefaultDict imported from typing (unused-import)
************* Module cirq.optimizers.eject_z
cirq/optimizers/eject_z.py:17:0: W0611: Unused Dict imported from typing (unused-import)
cirq/optimizers/eject_z.py:17:0: W0611: Unused List imported from typing (unused-import)
cirq/optimizers/eject_z.py:17:0: W0611: Unused Tuple imported from typing (unused-import)
************* Module cirq.work.pauli_sum_collector
cirq/work/pauli_sum_collector.py:16:0: W0611: Unused MutableMapping imported from typing (unused-import)
************* Module cirq.value.linear_dict
cirq/value/linear_dict.py:17:0: W0611: Unused Dict imported from typing (unused-import)
************* Module cirq.sim.simulator
cirq/sim/simulator.py:30:0: W0611: Unused Hashable imported from typing (unused-import)
cirq/sim/simulator.py:30:0: W0611: Unused Tuple imported from typing (unused-import)
************* Module cirq.sim.wave_function_simulator
cirq/sim/wave_function_simulator.py:19:0: W0611: Unused Hashable imported from typing (unused-import)
************* Module cirq.ops.linear_combinations
cirq/ops/linear_combinations.py:15:0: W0611: Unused DefaultDict imported from typing (unused-import)
************* Module cirq.ops.op_tree
cirq/ops/op_tree.py:20:0: W0611: Unused Dict imported from typing (unused-import)
************* Module cirq.ops.pauli_gates
cirq/ops/pauli_gates.py:15:0: W0611: Unused Optional imported from typing (unused-import)
************* Module cirq.experiments.qubit_characterizations
cirq/experiments/qubit_characterizations.py:8:0: W0611: Unused Axes3D imported from mpl_toolkits.mplot3d (unused-import)
************* Module cirq.google.serializable_gate_set
cirq/google/serializable_gate_set.py:18:0: W0611: Unused List imported from typing (unused-import)
cirq/google/serializable_gate_set.py:18:0: W0611: Unused Type imported from typing (unused-import)
************* Module cirq.google.engine.engine
cirq/google/engine/engine.py:33:0: W0611: Unused Tuple imported from typing (unused-import)
************* Module cirq.protocols.has_unitary
cirq/protocols/has_unitary.py:15:0: W0611: Unused Dict imported from typing (unused-import)
************* Module cirq.contrib.acquaintance.optimizers
cirq/contrib/acquaintance/optimizers.py:15:0: W0611: Unused FrozenSet imported from typing (unused-import)
cirq/contrib/acquaintance/optimizers.py:15:0: W0611: Unused List imported from typing (unused-import)
cirq/contrib/acquaintance/optimizers.py:15:0: W0611: Unused Set imported from typing (unused-import)
************* Module cirq.contrib.acquaintance.executor
cirq/contrib/acquaintance/executor.py:15:0: W0611: Unused List imported from typing (unused-import)
************* Module cirq.contrib.qasm_import._parser
cirq/contrib/qasm_import/_parser.py:16:0: W0611: Unused Dict imported from typing (unused-import)
cirq/contrib/qasm_import/_parser.py:16:0: W0611: Unused Optional imported from typing (unused-import)
************* Module cirq.contrib.paulistring.convert_to_pauli_string_phasors
cirq/contrib/paulistring/convert_to_pauli_string_phasors.py:15:0: W0611: Unused List imported from typing (unused-import)
************* Module cirq.vis.heatmap
cirq/vis/heatmap.py:29:0: W0611: Unused List imported from typing (unused-import)

```

I also have pylint==2.3.1, astroid==2.1.0. I always get these but i ignore them and they pass on Travis.
At least some of those are imports only used in a type comment.  The latest pylint version should handle that.
We are on the latest version on pylint, what we are not on the latest version of is astroid because this bug has not been fixed https://github.com/PyCQA/astroid/issues/650.
This is growing stale and we probably need someone to repo again to make progress.
I still notice pylint checks returning more results on my machine than in ci.

Resolving patch:
diff --git a/cirq/google/engine/engine.py b/cirq/google/engine/engine.py
--- a/cirq/google/engine/engine.py
+++ b/cirq/google/engine/engine.py
@@ -31,9 +31,8 @@
 from typing import (Dict, Iterable, List, Optional, Sequence, Set, TypeVar,
                     Union, TYPE_CHECKING)
 
-from cirq.google.engine.client import quantum
 from google.protobuf import any_pb2
-
+from cirq.google.engine.client import quantum
 from cirq import circuits, study, value
 from cirq.google import serializable_gate_set as sgs
 from cirq.google.api import v2


Test patch:
diff --git a/cirq/sim/clifford/stabilizer_sampler_test.py b/cirq/sim/clifford/stabilizer_sampler_test.py
--- a/cirq/sim/clifford/stabilizer_sampler_test.py
+++ b/cirq/sim/clifford/stabilizer_sampler_test.py
@@ -1,7 +1,21 @@
-import cirq
+# Copyright 2020 The Cirq Developers
+#
+# 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 numpy as np
 
+import cirq
+
 
 def test_produces_samples():
     a, b = cirq.LineQubit.range(2)
diff --git a/dev_tools/bash_scripts_test.py b/dev_tools/bash_scripts_test.py
--- a/dev_tools/bash_scripts_test.py
+++ b/dev_tools/bash_scripts_test.py
@@ -573,14 +573,14 @@ def test_pylint_changed_files_file_selection(tmpdir_factory):
                  tmpdir_factory=tmpdir_factory,
                  arg='HEAD~1',
                  setup='mkdir cirq dev_tools examples ignore\n'
-                 'touch cirq/file.py dev_tools/file.py examples/file.y\n'
+                 'touch cirq/file.py dev_tools/file.py examples/file.py\n'
                  'touch ignore/ignore.py\n'
                  'git add -A\n'
                  'git commit -m test --quiet --no-gpg-sign\n')
     print(result)
     assert result.exit_code == 0
     assert result.out == intercepted_prefix + ('cirq/file.py dev_tools/file.py '
-                                               'examples/file.y\n')
+                                               'examples/file.py\n')
     assert result.err.split() == (
         "Comparing against revision 'HEAD~1'.\n"
         "Found 3 lintable files associated with changes.\n").split()