diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..fc19f9a --- /dev/null +++ b/.coveragerc @@ -0,0 +1,6 @@ +[run] +branch = True +source = flake8_import_style + +[report] +show_missing = True diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93f7395 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.egg-info +*.pyc +__pycache__ +/dist +/build +/bin +/lib +/lib64 +/include +/share +/pip-selfcheck.json +/pyvenv.cfg +/htmlcov +/.coverage +/.tox diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..77afb77 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: python +sudo: false +python: + - "2.7" + - "3.4" + - "3.5" + - "3.6" +install: pip install tox tox-travis coveralls +script: tox +after_success: + coveralls diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4c04412 --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2016-2017, Stefano Palazzo + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/DESCRIPTION.rst b/DESCRIPTION.rst new file mode 100644 index 0000000..241d402 --- /dev/null +++ b/DESCRIPTION.rst @@ -0,0 +1,6 @@ +flake8-import-style +=================== + +A flake8 plugin to ensure explicit module imports. + +For more information, see `github.com/sfstpala/flake8-import-style `_. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..2a23af5 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,9 @@ +include README.md +include DESCRIPTION.rst +include COPYING +include Makefile +include requirements-dev.txt +include .coveragerc +include pip.conf +include tox.ini +include .travis.yml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1ccbc74 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +python ?= python3.6 +package = flake8_import_style + +all: $(package).egg-info +$(package).egg-info: setup.py requirements-dev.txt bin/pip + bin/pip install -r requirements-dev.txt && touch $@ +bin/pip: bin/python + bin/python -m pip install -I pip wheel +bin/python: + $(python) -m venv . + +test: all + bin/coverage run setup.py test + bin/coverage html + bin/coverage report --fail-under=100 + bin/flake8 setup.py $(package) + bin/check-manifest + bin/python setup.py check -mrs + bin/pip list --outdated + +clean: + rm -rf *.egg-info $(shell find $(package) -name "__pycache__") + rm -rf *.pyc $(shell find $(package) -name "*.pyc") + rm -rf bin lib lib64 include pip-selfcheck.json pyvenv.cfg + rm -rf share build dist .tox .coverage htmlcov diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1aed01 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# flake8-import-style + +[![Build](https://img.shields.io/travis/sfstpala/flake8-import-style.svg?style=flat-square)](https://travis-ci.org/sfstpala/flake8-import-style) +[![Coverage](https://img.shields.io/coveralls/sfstpala/flake8-import-style.svg?style=flat-square)](https://coveralls.io/r/sfstpala/flake8-import-style) +[![PyPI](https://img.shields.io/pypi/v/flake8-import-style.svg?style=flat-square)](https://pypi.python.org/pypi/flake8-import-style) + +A [flake8](http://flake8.pycqa.org/en/latest/) plugin to ensure explicit module imports. + + pip install flake8_import_style + flake8 *.py + +Errors (enabled by default): + + - `I801 use 'import ...' instead of 'from ... import ...'` + +Tested with Python 2.7, 3.4, 3.5, and 3.6. + +Type `make test` or `tox` to run the test suite in a virtual environment. diff --git a/flake8_import_style/__init__.py b/flake8_import_style/__init__.py new file mode 100644 index 0000000..05055fe --- /dev/null +++ b/flake8_import_style/__init__.py @@ -0,0 +1,24 @@ +import ast + +import pkg_resources + + +I801 = "I801 use 'import {module}' instead of 'from {module} import {names}'" + + +class I8(object): + """Complain about all "from x import y" style imports.""" + + name = "import-style" + version = pkg_resources.get_distribution(__package__).version + + def __init__(self, tree): + self.tree = tree + + def run(self): + for i in ast.walk(self.tree): + if isinstance(i, ast.ImportFrom): + message = I801.format( + module=(i.module or "..."), + names=", ".join(i.name for i in i.names)) + yield (i.lineno, i.col_offset, message, "I801") diff --git a/flake8_import_style/tests/__init__.py b/flake8_import_style/tests/__init__.py new file mode 100644 index 0000000..0925697 --- /dev/null +++ b/flake8_import_style/tests/__init__.py @@ -0,0 +1,44 @@ +import ast +import unittest + +import flake8_import_style + + +class I8Test(unittest.TestCase): + + def test_run(self): + + tree = ast.parse("import mod") + i8 = flake8_import_style.I8(tree) + self.assertEqual(list(i8.run()), []) + + tree = ast.parse("import mod as mod1") + i8 = flake8_import_style.I8(tree) + self.assertEqual(list(i8.run()), []) + + tree = ast.parse("from . import obj") + i8 = flake8_import_style.I8(tree) + self.assertEqual(list(i8.run()), [( + 1, + 0, + "I801 use 'import ...' instead of 'from ... import obj'", + "I801", + )]) + + tree = ast.parse("from .. import obj") + i8 = flake8_import_style.I8(tree) + self.assertEqual(list(i8.run()), [( + 1, + 0, + "I801 use 'import ...' instead of 'from ... import obj'", + "I801", + )]) + + tree = ast.parse("from mod import obj") + i8 = flake8_import_style.I8(tree) + self.assertEqual(list(i8.run()), [( + 1, + 0, + "I801 use 'import mod' instead of 'from mod import obj'", + "I801", + )]) diff --git a/pip.conf b/pip.conf new file mode 100644 index 0000000..3cdc986 --- /dev/null +++ b/pip.conf @@ -0,0 +1,4 @@ +[install] +upgrade = true +[list] +format = legacy diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..f897722 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,19 @@ +--editable . +setuptools +wheel +coverage +flake8 +flake8-docstrings +flake8-import-order +flake8-quotes +flake8-commas +flake8-blind-except +flake8-comprehensions +flake8-mutable +flake8-print +flake8-logging-format +flake8-mock +flake8-builtins +pep8-naming +check-manifest +docutils diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..e0d1abb --- /dev/null +++ b/setup.cfg @@ -0,0 +1,8 @@ +[bdist_wheel] +python-tag=py36 +[flake8] +max-complexity=10 +ignore=D100,D101,D102,D103,D104,D105 +import-order-style=cryptography +application-import-names=flake8_import_style +inline-quotes=double diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f2da930 --- /dev/null +++ b/setup.py @@ -0,0 +1,37 @@ +import os.path +import setuptools + + +here = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(here, "DESCRIPTION.rst")) as f: + long_description = f.read() + +setuptools.setup( + name="flake8-import-style", version="0.1.0", + description="A flake8 plugin to ensure explicit module imports", + long_description=long_description, + packages=setuptools.find_packages(), + author="Stefano Palazzo", + author_email="stefano.palazzo@gmail.com", + url="https://github.com/sfstpala/flake8-import-style", + license="ISC", + test_suite="flake8_import_style.tests", + entry_points={ + "flake8.extension": [ + "I8 = flake8_import_style:I8", + ], + }, + classifiers=[ + "Framework :: Flake8", + "License :: OSI Approved :: ISC License (ISCL)", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Quality Assurance", + ], +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..b76836f --- /dev/null +++ b/tox.ini @@ -0,0 +1,12 @@ +[tox] +envlist = py27,py34,py35,py36 + +[testenv] +deps= + -rrequirements-dev.txt +commands = + coverage run setup.py test + coverage report --fail-under=100 + flake8 setup.py flake8_import_style + check-manifest + python setup.py check -mrs