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

Add mypy support #228

Merged
merged 18 commits into from
Jul 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pip-log.txt
.coverage
.tox
nosetests.xml
.noseids

# Translations
*.mo
Expand All @@ -31,9 +32,13 @@ nosetests.xml
.project
.pydevproject
.idea
.vscode

# Sphinx
docs/_build

# Mypy
.mypy_cache

# emacs
TAGS
6 changes: 6 additions & 0 deletions .prospector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ frosted:
pyroma:
run: true

mypy:
run: true
options:
ignore-missing-imports: true
follow-imports: skip

pylint:
disable:
- bad-builtin
Expand Down
29 changes: 21 additions & 8 deletions docs/supported_tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Prospector will run with defaults enabled and optional extras disabled unless co

To specify an exact list of tools to run, for example, only pylint and pep8::

prospector --tool pylint --tool pep8
prospector --tool pylint --tool pep8

Note that this command line option will override values set in :doc:`profiles<profiles>`.

Expand All @@ -35,11 +35,11 @@ and is the source of most messages that prospector outputs.
`pep8.py <https://pep8.readthedocs.io/>`_
```````````````````````````````````````````````````

``pep8.py`` is a simple tool to warn about violations of the
``pep8.py`` is a simple tool to warn about violations of the
`PEP8 style guide <https://www.python.org/dev/peps/pep-0008/>`_. It produces
messages for any divergence from the style guide.

Prospector's concept of :doc:`strictness <profiles>` turns off various warnings
Prospector's concept of :doc:`strictness <profiles>` turns off various warnings
depending on the strictness level. By default, several PEP8 errors will be
supressed. To adjust this without adjusting the strictness of other tools, you have
some options::
Expand All @@ -50,7 +50,7 @@ some options::
# turn on complete pep8 checking:
prospector --full-pep8

# change the maximum line length allowed
# change the maximum line length allowed
# (the default varies by strictness):
prospector --max-line-length 120

Expand All @@ -75,7 +75,7 @@ methods.
```````````````````````````````````````````````

Dodgy is a very simple tool designed to find 'dodgy' things which should
not be in a public project, such as secret keys, passwords, AWS tokens or
not be in a public project, such as secret keys, passwords, AWS tokens or
source control diffs.

`pydocstyle <https://github.com/PyCQA/pydocstyle>`_
Expand Down Expand Up @@ -109,7 +109,7 @@ Optional Extras
These extras are integrated into prospector but are not activated by default.
This is because their output is not necessarily useful for all projects.

They are also not installed by default. The instructions for installing each tool is in the tool
They are also not installed by default. The instructions for installing each tool is in the tool
section below. To install all extras at the same time, install prospector using the ``with_everything`` option::

pip install prospector[with_everything]
Expand All @@ -118,7 +118,7 @@ section below. To install all extras at the same time, install prospector using
`Pyroma <https://github.com/regebro/pyroma>`_
````````````````````````````````````````````````
Pyroma is a tool to check your `setup.py` to ensure it is following best practices
of the Python packaging ecosystem. It will warn you if you are missing any package
of the Python packaging ecosystem. It will warn you if you are missing any package
metadata which would improve the quality of your package. This is recommended if you
intend to publish your code on PyPI.

Expand All @@ -133,7 +133,7 @@ To install and use::

Vulture finds unused classes, functions and variables in your code. This could
be useful if your project is an application rather than a library, however, if
you do a lot of dynamic access or metaprogramming, Vulture will likely warn
you do a lot of dynamic access or metaprogramming, Vulture will likely warn
about unused code that is in fact used.

To install and use::
Expand All @@ -153,3 +153,16 @@ To install and use::

pip install prospector[with_frosted]
prospector --with-tool frosted


`mypy <https://github.com/python/mypy>`_
``````````````````````````````````````````````````````
Mypy is an experimental optional static type checker for Python that aims to combine
the benefits of dynamic (or "duck") typing and static typing. Mypy combines the
expressive power and convenience of Python with a powerful type system and
compile-time type checking.

To install and use::

pip install prospector[with_mypy]
prospector --with-tool mypy
1 change: 1 addition & 0 deletions prospector/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def _optional_tool(name, package_name=None, tool_class_name=None, install_option
'frosted': _optional_tool('frosted'),
'vulture': _optional_tool('vulture'),
'pyroma': _optional_tool('pyroma'),
'mypy': _optional_tool('mypy'),
}


Expand Down
91 changes: 91 additions & 0 deletions prospector/tools/mypy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
from itertools import islice
from mypy import api

from prospector.message import Location, Message
from prospector.tools import ToolBase


__all__ = (
'MypyTool',
)


MYPY_OPTIONS = [
'allow',
'check',
'disallow',
'no-check',
'no-warn',
'warn'
]


class MypyTool(ToolBase):
def __init__(self, *args, **kwargs):
super(MypyTool, self).__init__(*args, **kwargs)
self.checker = api
self.options = ['--show-column-numbers']

def configure(self, prospector_config, _):
options = prospector_config.tool_options('mypy')

follow_imports = options.get('follow-imports', 'normal')
ignore_missing_imports = options.get('ignore-missing-imports', False)
implict_optional = options.get('implict-optional', False)
platform = options.get('platform', None)
python_2_mode = options.get('python-2-mode', False)
python_version = options.get('python-version', None)
strict_optional = options.get('strict-optional', False)

self.options.append('--follow-imports=%s' % follow_imports)

if ignore_missing_imports:
self.options.append('--ignore-missing-imports')

if implict_optional:
self.options.append('--implict-optional')

if platform:
self.options.append('--platform %s' % platform)

if python_2_mode:
self.options.append('--py2')

if python_version:
self.options.append('--python-version %s' % python_version)

if strict_optional:
self.options.append('--strict-optional')

for list_option in MYPY_OPTIONS:
for entry in options.get(list_option, []):
self.options.append('--%s-%s' % (list_option, entry))

def run(self, found_files):
paths = [path for path in found_files.iter_module_paths()]
paths.extend(self.options)
result = self.checker.run(paths)
report, _ = result[0], result[1:]
messages = []

for message in report.splitlines():
iter_message = iter(message.split(':'))
(path, line, char, err_type), err_msg = islice(iter_message, 4), list(message)
location = Location(
path=path,
module=None,
function=None,
line=line,
character=char,
absolute_path=True
)
message = Message(
source='mypy',
code=err_type,
location=location,
message=''.join(err_msg).strip()
)
messages.append(message)

return messages
6 changes: 6 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'License :: OSI Approved :: '
'GNU General Public License v2 or later (GPLv2+)',
)
Expand All @@ -59,6 +61,10 @@
'with_vulture': ('vulture>=0.6',),
'with_pyroma': ('pyroma>=2.3',),
}

if sys.version_info >= (3, 3):
_OPTIONAL['with_mypy'] = ('mypy>=0.600',)

with_everything = [req for req_list in _OPTIONAL.values() for req in req_list]
_OPTIONAL['with_everything'] = sorted(with_everything)

Expand Down