From 9f719f6454b18bb56aeded0a046c7de9452cf2b3 Mon Sep 17 00:00:00 2001 From: Erick Daniszewski Date: Sat, 3 Mar 2018 00:23:16 -0500 Subject: [PATCH] Cleanup (#10) * cleanup, update packaging, add dev targets, fix typos --- .gitignore | 4 +- .travis.yml | 45 +++----- LICENSE | 2 +- Makefile | 42 +++++++ Pipfile | 19 +++ Pipfile.lock | 218 +++++++++++++++++++++++++++++++++++ README.md | 51 ++++++-- pylint_quotes/__init__.py | 5 +- pylint_quotes/__version__.py | 12 ++ pylint_quotes/checker.py | 26 +++-- setup.cfg | 5 +- setup.py | 53 +++++---- tests/test_async_function.py | 4 +- tests/test_class.py | 4 +- tests/test_function.py | 4 +- tests/test_module.py | 4 +- tests/test_smart_quotes.py | 4 +- tests/test_string_literal.py | 4 +- tests/utils.py | 2 +- 19 files changed, 412 insertions(+), 96 deletions(-) create mode 100644 Makefile create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 pylint_quotes/__version__.py diff --git a/.gitignore b/.gitignore index eb1cd19..a9c5475 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ nosetests.xml coverage.xml *.cover .hypothesis/ +.pytest_cache # Translations *.mo @@ -102,6 +103,3 @@ ENV/ # PyCharm .idea - -# Make -Makefile \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 160bb62..dcd89b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,22 @@ language: python +python: + - "3.4" + - "3.5" + - "3.6" -matrix: - include: -# - python: 2.7 -# env: TOXENV=py27 -# - python: 2.7.6 -# env: TOXENV=py27 -# - python: 3.3 -# env: TOXENV=py33 - - python: 3.4 - env: TOXENV=py34 - - python: 3.5 - env: TOXENV=py35 - - python: 3.6 - env: TOXENV=py36 -before_install: - - python --version - - uname -a - - lsb_release -a +# install dependencies install: - - pip install tox pylint coveralls - - virtualenv --version - - easy_install --version - - pip --version - - tox --version + - pip install coveralls pytest-cov flake8 pylint isort + - pip install -e . + +cache: pip + +# run tests and linting script: - - pip install . - - pip install -U setuptools - - tox $TOXENV + - py.test --cov-report term --cov=pylint_quotes + - pylint pylint_quotes + - flake8 --ignore E501 pylint_quotes + - isort pylint_quotes -rc -c --diff + after_success: - coveralls -after_failure: - - more .tox/log/* | cat - - more .tox/*/log/* | cat diff --git a/LICENSE b/LICENSE index 902eec5..ee81dc4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Erick Daniszewski +Copyright (c) 2018 Erick Daniszewski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3d31e9 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +# +# Pylint Quotes +# + +PKG_VER := $(shell cat pylint_quotes/__version__.py | grep __version__ | awk '{print $$3}' | tr -d "'") + + +.PHONY: init +init: ## Initialize the repo for development + pip install pipenv + pipenv install --dev --skip-lock + +.PHONY: coverage +coverage: ## Run tests and report on coverage + pipenv run py.test --cov-report term --cov=pylint_quotes tests + +.PHONY: lint +lint: ## Lint the source code (pylint, flake8, isort) + pipenv run pylint pylint_quotes + pipenv run flake8 --ignore E501 pylint_quotes + pipenv run isort pylint_quotes -rc -c --diff + +.PHONY: publish +publish: ## Publish to PyPi + pip install 'twine>=1.5.0' + python setup.py sdist bdist_wheel + twine upload dist/* + rm -rf build dist .egg pylint_quotes.egg-info + +.PHONY: test +test: ## Run unit tests + pipenv run py.test + +.PHONY: version +version: ## Print the version of Synse Server + @echo "$(PKG_VER)" + +.PHONY: help +help: ## Print Make usage information + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort + +.DEFAULT_GOAL := help \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..9dc2698 --- /dev/null +++ b/Pipfile @@ -0,0 +1,19 @@ +[[source]] + +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + + +[packages] + +"e1839a8" = {path = ".", editable = true} + + +[dev-packages] + +pytest = ">=3.4.0" +coverage = "*" +pytest-cov = "*" +"flake8" = "*" +isort = "*" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..31d37f0 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,218 @@ +{ + "_meta": { + "hash": { + "sha256": "945e90355524b157da87973869b0b40cda6800a30e4c6d29099f3cbbec1204e6" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "astroid": { + "hashes": [ + "sha256:db5cfc9af6e0b60cd07c19478fb54021fc20d2d189882fbcbc94fc69a8aecc58", + "sha256:f0a0e386dbca9f93ea9f3ea6f32b37a24720502b7baa9cb17c3976a680d43a06" + ], + "version": "==1.6.1" + }, + "e1839a8": { + "editable": true, + "path": "." + }, + "isort": { + "hashes": [ + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497", + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8" + ], + "version": "==4.3.4" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", + "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", + "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", + "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", + "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", + "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", + "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", + "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", + "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", + "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", + "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", + "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", + "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", + "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", + "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", + "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", + "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", + "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b", + "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", + "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", + "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", + "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", + "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", + "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", + "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", + "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", + "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", + "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", + "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a" + ], + "version": "==1.3.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "pylint": { + "hashes": [ + "sha256:156839bedaa798febee72893beef00c650c2e7abafb5586fc7a6a56be7f80412", + "sha256:4fe3b99da7e789545327b75548cee6b511e4faa98afe268130fea1af4b5ec022" + ], + "version": "==1.8.2" + }, + "six": { + "hashes": [ + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" + ], + "version": "==1.11.0" + }, + "wrapt": { + "hashes": [ + "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" + ], + "version": "==1.10.11" + } + }, + "develop": { + "attrs": { + "hashes": [ + "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450", + "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9" + ], + "version": "==17.4.0" + }, + "coverage": { + "hashes": [ + "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", + "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", + "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", + "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", + "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", + "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", + "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", + "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", + "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", + "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", + "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", + "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", + "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", + "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", + "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", + "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", + "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", + "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", + "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", + "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", + "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", + "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", + "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", + "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", + "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", + "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", + "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", + "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", + "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", + "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", + "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", + "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", + "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", + "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", + "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", + "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" + ], + "version": "==4.5.1" + }, + "flake8": { + "hashes": [ + "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37", + "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0" + ], + "version": "==3.5.0" + }, + "isort": { + "hashes": [ + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497", + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8" + ], + "version": "==4.3.4" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "pluggy": { + "hashes": [ + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff" + ], + "version": "==0.6.0" + }, + "py": { + "hashes": [ + "sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f", + "sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d" + ], + "version": "==1.5.2" + }, + "pycodestyle": { + "hashes": [ + "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9", + "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766" + ], + "version": "==2.3.1" + }, + "pyflakes": { + "hashes": [ + "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", + "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" + ], + "version": "==1.6.0" + }, + "pytest": { + "hashes": [ + "sha256:8970e25181e15ab14ae895599a0a0e0ade7d1f1c4c8ca1072ce16f25526a184d", + "sha256:9ddcb879c8cc859d2540204b5399011f842e5e8823674bf429f70ada281b3cc6" + ], + "version": "==3.4.1" + }, + "pytest-cov": { + "hashes": [ + "sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec", + "sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d" + ], + "version": "==2.5.1" + }, + "six": { + "hashes": [ + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" + ], + "version": "==1.11.0" + } + } +} diff --git a/README.md b/README.md index 03c97f7..c4beb7f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build Status](https://travis-ci.org/edaniszewski/pylint-quotes.svg?branch=master)](https://travis-ci.org/edaniszewski/pylint-quotes) [![Coverage Status](https://coveralls.io/repos/github/edaniszewski/pylint-quotes/badge.svg?branch=master)](https://coveralls.io/github/edaniszewski/pylint-quotes?branch=master) [![Latest Version](https://img.shields.io/pypi/v/pylint-quotes.svg)](https://pypi.python.org/pypi/pylint-quotes) +[![License](https://img.shields.io/github/license/edaniszewski/pylint-quotes.svg)](LICENSE) A Pylint plugin for checking the consistency of string quotes. @@ -12,8 +13,7 @@ Below is an example python file that uses inconsistent string quotes. `example.py` ```python -"""Example python file. -""" +"""Example python file.""" def main(output="default"): @@ -28,14 +28,16 @@ if __name__ == "__main__": ``` which would yield ``` +➜ pylint --load-plugins pylint_quotes example.py + No config file found, using default configuration ************* Module example -C: 5, 0: Invalid string quote ", should be ' (invalid-string-quote) -C: 12, 0: Invalid string quote ", should be ' (invalid-string-quote) -C: 6, 0: Invalid docstring quote ''', should be """ (invalid-docstring-quote) +C: 4, 0: Invalid string quote ", should be ' (invalid-string-quote) +C: 11, 0: Invalid string quote ", should be ' (invalid-string-quote) +C: 5, 0: Invalid docstring quote ''', should be """ (invalid-docstring-quote) ------------------------------------------------------------------- -Your code has been rated at 2.50/10 (previous run: 2.50/10, +0.00) +----------------------------------- +Your code has been rated at 2.50/10 ``` ### after @@ -43,8 +45,7 @@ Fixing up the example above based on linting recommendations, `example.py` ```python -"""Example python file. -""" +"""Example python file.""" def main(output='default'): @@ -59,6 +60,8 @@ if __name__ == '__main__': ``` which yields ``` +➜ pylint --load-plugins pylint_quotes example.py + No config file found, using default configuration ------------------------------------------------------------------- @@ -67,10 +70,16 @@ Your code has been rated at 10.00/10 (previous run: 2.50/10, +7.50) ## Installation +Installing with `pip`: ``` pip install pylint-quotes ``` +Installing with `pipenev`: +``` +pipenv install pylint-quotes +``` + ## Usage To use pylint-quotes, it must loaded in as a plugin when running pylint ``` @@ -97,7 +106,7 @@ between example """ ``` - - docstrings (module, class, function) + - docstrings (module, class, function, async function) ```python def x(): '''Example''' @@ -108,6 +117,11 @@ between Multi-line example. """ pass + + async def z(): + """Async example. + """ + pass ``` ## Configuration @@ -131,3 +145,20 @@ Additionally the `string-quote` can be configured to avoid escaping: by default it enforces one type but if using the other type would avoid some escaping then it enforces the other one. To use those smart types the config is 'single-avoid-escape', and 'double-avoid-escape'. + + +## Developing +If you wish to develop the pylint-quotes project to fix a bug, add a feature, or +extend it for your own uses, the [Makefile](Makefile) provides a bunch of helpful +development targets. For a full list of the targets, see the Makefile, or you can +use `make help`. + +For convenience, `pipenv` is used to manage development dependencies. Before starting +development, you should `make init` to install `pipenv` if you don't already have it and +create a virtualenv with the project development dependencies. From there, you can use: +- `make test` to run the unit tests +- `make coverage` to run unit tests and get a coverage report +- `make lint` to perform source code linting + +## License +Pylint-quotes is licensed under an MIT license -- see [LICENSE](LICENSE) for more info. \ No newline at end of file diff --git a/pylint_quotes/__init__.py b/pylint_quotes/__init__.py index 5a697e5..8464f96 100644 --- a/pylint_quotes/__init__.py +++ b/pylint_quotes/__init__.py @@ -1,8 +1,7 @@ """pylint-quotes module""" from __future__ import absolute_import -from pylint_quotes import plugin, checker +from pylint_quotes import plugin, checker # noqa: F401 -__version__ = '0.1.8' -register = plugin.register +register = plugin.register # pylint: disable=invalid-name diff --git a/pylint_quotes/__version__.py b/pylint_quotes/__version__.py new file mode 100644 index 0000000..5e76017 --- /dev/null +++ b/pylint_quotes/__version__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +"""Pylint-quotes meta info.""" + + +__title__ = 'pylint-quotes' +__description__ = 'Quote consistency checker for PyLint..' +__url__ = 'https://github.com/edaniszewski/pylint-quotes' +__version__ = '0.1.9' +__author__ = 'Erick Daniszewski' +__author_email__ = 'edaniszewski@gmail.com' +__license__ = 'MIT' +__copyright__ = 'Copyright 2018 Erick Daniszewski' diff --git a/pylint_quotes/checker.py b/pylint_quotes/checker.py index d0fcce5..f70056e 100644 --- a/pylint_quotes/checker.py +++ b/pylint_quotes/checker.py @@ -1,13 +1,11 @@ -"""Pylint plugin for checking quote type on strings. -""" +"""Pylint plugin for checking quote type on strings.""" from __future__ import absolute_import import tokenize -from pylint.interfaces import ITokenChecker, IAstroidChecker from pylint.checkers import BaseTokenChecker - +from pylint.interfaces import IAstroidChecker, ITokenChecker CONFIG_OPTS = ('single', 'double') SMART_CONFIG_OPTS = tuple('%s-avoid-escape' % c for c in CONFIG_OPTS) @@ -163,7 +161,7 @@ def _process_for_docstring(self, node, node_type): # if there are no nodes that make up the body, then all we # have is the module docstring - if len(node.body) == 0: + if not node.body: # in this case, we should only have the module docstring # parsed in the node, so the only record in the # self._tokenized_triple_quotes dict will correspond to @@ -189,10 +187,10 @@ def _process_for_docstring(self, node, node_type): # quotes to find a matching docstring token that follows the # function/class definition. - if len(node.body) == 0: - # if there is no body to the class, the class def only contains - # the docstring, so the only quotes we are tracking should - # correspond to the class docstring. + if not node.body: + # if there is no body to the class, the class def only + # contains the docstring, so the only quotes we are + # tracking should correspond to the class docstring. lineno = self._find_docstring_line_for_no_body(node.fromlineno) quote_record = self._tokenized_triple_quotes.get(lineno) if quote_record: @@ -225,6 +223,7 @@ def _find_docstring_line_for_no_body(self, start): for i in tracked: if min(start, i) == start: return i + return None def _find_docstring_line(self, start, end): """Find the row where a docstring starts in a function or class. @@ -242,6 +241,7 @@ def _find_docstring_line(self, start, end): for i in range(start, end + 1): if i in self._tokenized_triple_quotes: return i + return None def process_tokens(self, tokens): """Process the token stream. @@ -286,11 +286,15 @@ def _process_string_token(self, token, start_row): if self.config.string_quote in SMART_CONFIG_OPTS: other_quote = next(q for q in QUOTES if q != preferred_quote) # If using the other quote avoids escaping, we switch to the other quote. - if preferred_quote in token[i+1:-1] and other_quote not in token[i+1:-1]: + if preferred_quote in token[i + 1:-1] and other_quote not in token[i + 1:-1]: preferred_quote = other_quote if norm_quote[0] != preferred_quote: - self._invalid_string_quote(norm_quote[0], start_row, correct_quote=preferred_quote) + self._invalid_string_quote( + quote=norm_quote[0], + row=start_row, + correct_quote=preferred_quote + ) def _check_triple_quotes(self, quote_record): """Check if the triple quote from tokenization is valid. diff --git a/setup.cfg b/setup.cfg index 3c6e79c..ed8a958 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,5 @@ [bdist_wheel] -universal=1 +universal = 1 + +[metadata] +license_file = LICENSE diff --git a/setup.py b/setup.py index d67d2cf..1a8c014 100644 --- a/setup.py +++ b/setup.py @@ -1,41 +1,44 @@ -"""Setup for the pylint-quotes package. -""" +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Setup for the pylint-quotes package.""" import os -import re from setuptools import setup, find_packages +here = os.path.abspath(os.path.dirname(__file__)) -def find_version(*file_paths): - """Return version defined in __init__.py without import pylint""" - with open(os.path.join(*file_paths)) as fhandler: - version_file = fhandler.read() - version_match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', - version_file, re.M) - if version_match: - return version_match.group(1) - raise RuntimeError('Unable to find version string.') +about = {} +with open(os.path.join(here, 'pylint_quotes', '__version__.py'), 'r') as f: + exec(f.read(), about) setup( - name='pylint-quotes', - description='Quote consistency checker for Pylint', - license='MIT', - version=find_version("pylint_quotes", "__init__.py"), - author='Erick Daniszewski', - author_email='edaniszewski@gmail.com', - url='https://github.com/edaniszewski/pylint-quotes', + name=about['__title__'], + description=about['__description__'], + license=about['__license__'], + version=about['__version__'], + author=about['__author__'], + author_email=about['__author_email__'], + url=about['__url__'], install_requires=[ - 'pylint', + 'pylint>=1.7.6', ], - packages=find_packages(), - classifiers=[ + python_requires=">=3.4", + packages=['pylint_quotes'], + zip_safe=False, + classifiers=( 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', 'Natural Language :: English', + 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development', 'Topic :: Utilities' - ], - keywords='pylint linting string quotes' + ), + keywords='pylint linting string quotes', ) diff --git a/tests/test_async_function.py b/tests/test_async_function.py index 9fa2997..82ca545 100644 --- a/tests/test_async_function.py +++ b/tests/test_async_function.py @@ -7,11 +7,11 @@ from pylint_quotes.checker import StringQuoteChecker from pylint.testutils import Message, set_config -from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuiteCheckerTestCase +from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuoteCheckerTestCase @pytest.mark.skipif(sys.version_info < (3, 5), reason='requires python3.5 or python3.6') -class TestAsyncFunctionStringQuoteChecker(StringQuiteCheckerTestCase): +class TestAsyncFunctionStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for asynchronous function-level docstrings. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/test_class.py b/tests/test_class.py index 76c74ea..86dfdb2 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -4,10 +4,10 @@ from pylint_quotes.checker import StringQuoteChecker from pylint.testutils import Message, set_config -from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuiteCheckerTestCase +from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuoteCheckerTestCase -class TestClassStringQuoteChecker(StringQuiteCheckerTestCase): +class TestClassStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for class-level docstrings. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/test_function.py b/tests/test_function.py index e1accbb..bdbbb40 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -4,10 +4,10 @@ from pylint_quotes.checker import StringQuoteChecker from pylint.testutils import Message, set_config -from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuiteCheckerTestCase +from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuoteCheckerTestCase -class TestFunctionStringQuoteChecker(StringQuiteCheckerTestCase): +class TestFunctionStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for function-level docstrings. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/test_module.py b/tests/test_module.py index bb84d94..8eea2a6 100644 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -4,10 +4,10 @@ from pylint_quotes.checker import StringQuoteChecker from pylint.testutils import Message, set_config -from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuiteCheckerTestCase +from utils import TRI_Q_DOUB, TRI_Q_SING, StringQuoteCheckerTestCase -class TestModuleStringQuoteChecker(StringQuiteCheckerTestCase): +class TestModuleStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for module-level docstrings. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/test_smart_quotes.py b/tests/test_smart_quotes.py index 19f178f..32e77b8 100644 --- a/tests/test_smart_quotes.py +++ b/tests/test_smart_quotes.py @@ -12,10 +12,10 @@ except ImportError: from pylint.testutils import _tokenize_str as tokenize_str -from utils import Q_DOUB, Q_SING, TRI_Q_SING, TRI_Q_DOUB, StringQuiteCheckerTestCase +from utils import Q_DOUB, Q_SING, TRI_Q_SING, TRI_Q_DOUB, StringQuoteCheckerTestCase -class TestSmartStringQuoteChecker(StringQuiteCheckerTestCase): +class TestSmartStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for smart escaping string literals. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/test_string_literal.py b/tests/test_string_literal.py index 83bc4c7..39ab5fe 100644 --- a/tests/test_string_literal.py +++ b/tests/test_string_literal.py @@ -9,10 +9,10 @@ except ImportError: from pylint.testutils import _tokenize_str as tokenize_str -from utils import Q_DOUB, Q_SING, TRI_Q_SING, TRI_Q_DOUB, StringQuiteCheckerTestCase +from utils import Q_DOUB, Q_SING, TRI_Q_SING, TRI_Q_DOUB, StringQuoteCheckerTestCase -class TestStringLiteralStringQuoteChecker(StringQuiteCheckerTestCase): +class TestStringLiteralStringQuoteChecker(StringQuoteCheckerTestCase): """ Test case for string literals. """ CHECKER_CLASS = StringQuoteChecker diff --git a/tests/utils.py b/tests/utils.py index 24bc9bf..39f41b3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -19,7 +19,7 @@ TRI_Q_DOUB = '"""' -class StringQuiteCheckerTestCase(CheckerTestCase): +class StringQuoteCheckerTestCase(CheckerTestCase): """A class which extends the pylint CheckerTestCase by wrapping some common code used in testing. """