Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align mypy interpreter constraint with reality. #7754

Merged
merged 1 commit into from May 18, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -27,6 +27,7 @@
class MypyTask(ResolveRequirementsTaskBase):
"""Invoke the mypy static type analyzer for Python."""

_MYPY_COMPATIBLE_INTERPETER_CONSTRAINT = '>=3.5'
This conversation was marked as resolved by jsirois

This comment has been minimized.

Copy link
@stuhood

stuhood May 17, 2019

Member

This might change over time with the version of mypy that is in use (which is itself configurable). It should probably move into an option next to the version.

This comment has been minimized.

Copy link
@Eric-Arellano

Eric-Arellano May 17, 2019

Contributor

I would wait to make this an option until MyPy changes the minimum required version to not support 3.5. Keep it as simple as possible for now.

This comment has been minimized.

Copy link
@stuhood

stuhood May 18, 2019

Member

Alrighty. Not a blocker.

This comment has been minimized.

Copy link
@jsirois

jsirois May 18, 2019

Author Member

OK - thanks. I'll merge as-is and we'll fix when we hit an error due to mypy bump of the floor here.

_PYTHON_SOURCE_EXTENSION = '.py'

@classmethod
@@ -48,8 +49,10 @@ def supports_passthru_args(cls):
def subsystem_dependencies(cls):
return super(MypyTask, cls).subsystem_dependencies() + (PythonInterpreterCache,)

def find_py3_interpreter(self):
interpreters = self._interpreter_cache.setup(filters=['>=3'])
def find_mypy_interpreter(self):
interpreters = self._interpreter_cache.setup(
filters=[self._MYPY_COMPATIBLE_INTERPETER_CONSTRAINT]
)
return min(interpreters) if interpreters else None

@staticmethod
@@ -101,17 +104,20 @@ def _run_mypy(self, py3_interpreter, mypy_args, **kwargs):
return pex.run(mypy_args, **kwargs)

def execute(self):
py3_interpreter = self.find_py3_interpreter()
if not py3_interpreter:
raise TaskError('Unable to find a Python 3.x interpreter (required for mypy).')
mypy_interpreter = self.find_mypy_interpreter()
if not mypy_interpreter:
raise TaskError('Unable to find a Python {} interpreter (required for mypy).'
.format(self._MYPY_COMPATIBLE_INTERPETER_CONSTRAINT))

sources = self._calculate_python_sources(self.context.target_roots)
if not sources:
self.context.log.debug('No Python sources to check.')
return

# Determine interpreter used by the sources so we can tell mypy.
interpreter_for_targets = self._interpreter_cache.select_interpreter_for_targets(self.context.target_roots)
interpreter_for_targets = self._interpreter_cache.select_interpreter_for_targets(
self.context.target_roots
)
if not interpreter_for_targets:
raise TaskError('No Python interpreter compatible with specified sources.')

@@ -141,7 +147,7 @@ def execute(self):
log_config=WorkUnit.LogConfig(level=self.get_options().level,
colors=self.get_options().colors),
cmd=' '.join(cmd)) as workunit:
returncode = self._run_mypy(py3_interpreter, cmd,
returncode = self._run_mypy(mypy_interpreter, cmd,
env={'MYPYPATH': mypy_path}, stdout=workunit.output('stdout'), stderr=subprocess.STDOUT)
if returncode != 0:
raise TaskError('mypy failed: code={}'.format(returncode))
@@ -4,7 +4,7 @@

from __future__ import absolute_import, division, print_function, unicode_literals

from pants_test.backend.python.interpreter_selection_utils import PY_3, has_python_version
from pants_test.backend.python.interpreter_selection_utils import has_python_version
from pants_test.pants_run_integration_test import PantsRunIntegrationTest


@@ -16,13 +16,14 @@ def test_mypy(self):
'--',
'--follow-imports=silent'
]
if has_python_version(PY_3):
# Python 3.x is available. Test that we see an error in this integration test.

if any((has_python_version('3.{}'.format(v)) for v in (5, 6, 7, 8))):
# Python 3.5+ is available. Test that we see an error in this integration test.
with self.pants_results(cmd) as pants_run:
self.assert_success(pants_run)
else:
# Python 3.x was not found. Test whether mypy task fails for that reason.
# Python 3.5+ was not found. Test whether mypy task fails for that reason.
with self.pants_results(cmd) as pants_run:
self.assert_failure(pants_run)
self.assertIn('Unable to find a Python 3.x interpreter (required for mypy)',
self.assertIn('Unable to find a Python >=3.5 interpreter (required for mypy)',
pants_run.stdout_data)
@@ -15,20 +15,8 @@
PY_2 = '2'
PY_3 = '3'

PY_26 = '2.6'
PY_27 = '2.7'
PY_34 = '3.4'
PY_35 = '3.5'
PY_36 = '3.6'
PY_37 = '3.7'
PY_38 = '3.8'


def find_all_pythons_present(*versions):
"""Return sorted list of all Python versions present on the system."""
if not versions:
versions = {PY_26, PY_27, PY_34, PY_35, PY_36, PY_37, PY_38}
return sorted(version for version in versions if has_python_version(version))


def has_python_version(version):
@@ -58,16 +46,6 @@ def python_interpreter_path(version):
return None


def skip_unless_any_pythons_present(*versions):
"""A decorator that only runs the decorated test method if any of the specified pythons are present.
:param string *versions: Python version strings, such as 2.7, 3.
"""
if any(v for v in versions if has_python_version(v)):
return skipIf(False, 'At least one of the expected python versions found.')
return skipIf(True, 'Could not find at least one of the required pythons from {} on the system. Skipping.'.format(versions))


def skip_unless_all_pythons_present(*versions):
"""A decorator that only runs the decorated test method if all of the specified pythons are present.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.