From fec0603c8f3cfc89f1b19055fd6a3463af80bd47 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 2 Apr 2018 19:46:51 -0400 Subject: [PATCH] Update tooling --- .coveragerc | 4 +- .gitignore | 3 +- .verchew.ini | 4 +- CONTRIBUTING.md | 2 +- LICENSE.md | 4 +- Makefile | 98 ++++++++++++++------------------------ Pipfile | 11 ++++- Pipfile.lock | 122 ++++++++++++++++++++++++++++++++++++++++++++++-- bin/verchew | 51 ++++++++++++-------- gitman.yml | 2 +- scent.py | 2 +- setup.py | 6 +-- 12 files changed, 204 insertions(+), 105 deletions(-) diff --git a/.coveragerc b/.coveragerc index 1fcaece7..5033e7f3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,7 @@ [run] + branch = true + omit = - */.venv/* + .venv/* */tests/* diff --git a/.gitignore b/.gitignore index 71d28986..703d0167 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ __pycache__ Icon* # Temporary virtual environment files -/.cache/ +/.*cache/ /.venv/ # Temporary server files @@ -34,7 +34,6 @@ Icon* *.gdraw # Testing and coverage results -/.pytest/ /.coverage /.coverage.* /htmlcov/ diff --git a/.verchew.ini b/.verchew.ini index 8f86b07f..e270feff 100644 --- a/.verchew.ini +++ b/.verchew.ini @@ -11,7 +11,7 @@ version = Python 3. [pipenv] cli = pipenv -version = 9. +versions = 10. | 11. [Git] @@ -22,7 +22,7 @@ version = 2. cli = pandoc version = 1. -option = true +optional = true message = This is only needed to generate the README for PyPI. [Graphviz] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3588cbd2..19feb0de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,7 +49,7 @@ $ make watch Build the documentation: ```sh -$ make doc +$ make docs ``` ### Static Analysis diff --git a/LICENSE.md b/LICENSE.md index 35f0336e..56160e6c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,8 +1,6 @@ -# License - **The MIT License (MIT)** -Copyright © 2017, Jace Browning +Copyright © 2015, Jace Browning 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 index 31907363..72fd1796 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,11 @@ CONFIG := $(wildcard *.py) MODULES := $(wildcard $(PACKAGE)/*.py) # Virtual environment paths -export PIPENV_SHELL_COMPAT=true export PIPENV_VENV_IN_PROJECT=true export PIPENV_IGNORE_VIRTUALENVS=true -ENV := .venv +VENV := .venv -# MAIN TASKS ################################################################### +# MAIN TASKS ################################################################## SNIFFER := pipenv run sniffer @@ -44,21 +43,17 @@ doctor: ## Confirm system dependencies are available # PROJECT DEPENDENCIES ######################################################### -DEPENDENCIES := $(ENV)/.pipenv-$(shell bin/checksum Pipfile*) -METADATA := *.egg-info +DEPENDENCIES := $(VENV)/.pipenv-$(shell bin/checksum Pipfile* setup.py) .PHONY: install -install: $(DEPENDENCIES) $(METADATA) +install: $(DEPENDENCIES) $(DEPENDENCIES): - pipenv install --dev - @ touch $@ - -$(METADATA): setup.py pipenv run python setup.py develop + pipenv install --dev @ touch $@ -# CHECKS ####################################################################### +# CHECKS ###################################################################### PYLINT := pipenv run pylint PYCODESTYLE := pipenv run pycodestyle @@ -79,7 +74,7 @@ pycodestyle: install pydocstyle: install $(PYDOCSTYLE) $(PACKAGES) $(CONFIG) -# TESTS ######################################################################## +# TESTS ####################################################################### PYTEST := pipenv run py.test COVERAGE := pipenv run coverage @@ -104,38 +99,38 @@ test: test-all ## Run unit and integration tests .PHONY: test-unit test-unit: install - @- mv $(FAILURES) $(FAILURES).bak + @ ( mv $(FAILURES) $(FAILURES).bak || true ) > /dev/null 2>&1 $(PYTEST) $(PYTEST_OPTIONS) $(PACKAGE) --junitxml=$(REPORTS)/unit.xml - @- mv $(FAILURES).bak $(FAILURES) + @ ( mv $(FAILURES).bak $(FAILURES) || true ) > /dev/null 2>&1 $(COVERAGE_SPACE) $(REPOSITORY) unit .PHONY: test-int test-int: install - @ if test -e $(FAILURES); then $(PYTEST) $(PYTEST_RERUN_OPTIONS) tests; fi + @ if test -e $(FAILURES); then TEST_INTEGRATION=true $(PYTEST) $(PYTEST_RERUN_OPTIONS) tests; fi @ rm -rf $(FAILURES) - $(PYTEST) $(PYTEST_OPTIONS) tests --junitxml=$(REPORTS)/integration.xml + TEST_INTEGRATION=true $(PYTEST) $(PYTEST_OPTIONS) tests --junitxml=$(REPORTS)/integration.xml $(COVERAGE_SPACE) $(REPOSITORY) integration .PHONY: test-all test-all: install - @ if test -e $(FAILURES); then $(PYTEST) $(PYTEST_RERUN_OPTIONS) $(PACKAGES); fi + @ if test -e $(FAILURES); then TEST_INTEGRATION=true $(PYTEST) $(PYTEST_RERUN_OPTIONS) $(PACKAGES); fi @ rm -rf $(FAILURES) - $(PYTEST) $(PYTEST_OPTIONS) $(PACKAGES) --junitxml=$(REPORTS)/overall.xml + TEST_INTEGRATION=true $(PYTEST) $(PYTEST_OPTIONS) $(PACKAGES) --junitxml=$(REPORTS)/overall.xml $(COVERAGE_SPACE) $(REPOSITORY) overall .PHONY: read-coverage read-coverage: bin/open htmlcov/index.html -# DOCUMENTATION ################################################################ +# DOCUMENTATION ############################################################### PYREVERSE := pipenv run pyreverse MKDOCS := pipenv run mkdocs MKDOCS_INDEX := site/index.html -.PHONY: doc -doc: uml mkdocs ## Generate documentation +.PHONY: docs +docs: uml mkdocs ## Generate documentation .PHONY: docs/demo.gif docs/demo.gif: @@ -169,7 +164,7 @@ mkdocs-live: mkdocs eval "sleep 3; bin/open http://127.0.0.1:8000" & $(MKDOCS) serve -# BUILD ######################################################################## +# BUILD ####################################################################### PYINSTALLER := pipenv run pyinstaller PYINSTALLER_MAKESPEC := pipenv run pyi-makespec @@ -177,6 +172,9 @@ PYINSTALLER_MAKESPEC := pipenv run pyi-makespec DIST_FILES := dist/*.tar.gz dist/*.whl EXE_FILES := dist/$(PROJECT).* +.PHONY: build +build: dist + .PHONY: dist dist: install $(DIST_FILES) $(DIST_FILES): $(MODULES) README.rst CHANGELOG.rst @@ -197,68 +195,44 @@ $(EXE_FILES): $(MODULES) $(PROJECT).spec $(PROJECT).spec: $(PYINSTALLER_MAKESPEC) $(PACKAGE)/__main__.py --onefile --windowed --name=$(PROJECT) -# RELEASE ###################################################################### +# RELEASE ##################################################################### TWINE := pipenv run twine -.PHONY: register -register: dist ## Register the project on PyPI - @ echo NOTE: your project must be registered manually - @ echo https://github.com/pypa/python-packaging-user-guide/issues/263 - # TODO: switch to twine when the above issue is resolved - # $(TWINE) register dist/*.whl - .PHONY: upload -upload: .git-no-changes register ## Upload the current version to PyPI +upload: dist ## Upload the current version to PyPI + git diff --name-only --exit-code $(TWINE) upload dist/*.* bin/open https://pypi.python.org/pypi/$(PROJECT) -.PHONY: .git-no-changes -.git-no-changes: - @ if git diff --name-only --exit-code; \ - then \ - echo Git working copy is clean...; \ - else \ - echo ERROR: Git working copy is dirty!; \ - echo Commit your changes and try again.; \ - exit -1; \ - fi; - -# CLEANUP ###################################################################### +# CLEANUP ##################################################################### .PHONY: clean -clean: .clean-dist .clean-test .clean-doc .clean-build ## Delete all generated and temporary files +clean: .clean-build .clean-docs .clean-test .clean-install ## Delete all generated and temporary files .PHONY: clean-all -clean-all: clean .clean-env .clean-workspace +clean-all: clean + rm -rf $(VENV) -.PHONY: .clean-build -.clean-build: +.PHONY: .clean-install +.clean-install: find $(PACKAGES) -name '*.pyc' -delete find $(PACKAGES) -name '__pycache__' -delete rm -rf *.egg-info -.PHONY: .clean-doc -.clean-doc: - rm -rf README.rst docs/apidocs *.html docs/*.png site - .PHONY: .clean-test .clean-test: rm -rf .cache .pytest .coverage htmlcov xmlreport -.PHONY: .clean-dist -.clean-dist: - rm -rf *.spec dist build - -.PHONY: .clean-env -.clean-env: clean - rm -rf $(ENV) +.PHONY: .clean-docs +.clean-docs: + rm -rf *.rst docs/apidocs *.html docs/*.png site -.PHONY: .clean-workspace -.clean-workspace: - rm -rf *.sublime-workspace +.PHONY: .clean-build +.clean-build: + rm -rf *.spec dist build -# HELP ######################################################################### +# HELP ######################################################################## .PHONY: help help: all diff --git a/Pipfile b/Pipfile index 1425c988..68d3aaf7 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,10 @@ name = "pypi" python_version = "3" +[packages] + +gitman = { path = ".", editable = true } + [dev-packages] # Linters @@ -19,11 +23,11 @@ pydocstyle = "~=2.0" pytest = "~=3.3" pytest-describe = "*" pytest-expecter = "*" -pytest-cov = "*" pytest-random = "*" +pytest-cov = "*" freezegun = "*" -# Coverage +# Reports coverage-space = "*" # Documentation @@ -33,9 +37,12 @@ pygments = "*" # Build wheel = "*" +pyinstaller = "*" # Release twine = "*" # Tooling sniffer = "*" +pync = { version = "<2.0", sys_platform = "== 'darwin'" } +MacFSEvents = { version = "*", sys_platform = "== 'darwin'" } diff --git a/Pipfile.lock b/Pipfile.lock index 2948ff5c..f993af87 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4bdd6716c94368c93957208452fa59ad53d55c35a40cd021331d1696642b08bd" + "sha256": "be59c912bea16421b668d8b6308518bec391a5c257f2fe765c00cc26b752ae30" }, "pipfile-spec": 6, "requires": { @@ -15,8 +15,78 @@ } ] }, - "default": {}, + "default": { + "gitman": { + "editable": true, + "path": "." + }, + "parse": { + "hashes": [ + "sha256:8048dde3f5ca07ad7ac7350460952d83b63eaacecdac1b37f45fd74870d849d2" + ], + "version": "==1.8.2" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "version": "==3.12" + }, + "simplejson": { + "hashes": [ + "sha256:06b69946903ffd593d45624bdc354c1b857c2b1690ed2112df88d0e4e0294b06", + "sha256:194fa08e4047f16e7087f2a406abd15151a482a097e42d8babb1b8181b2232b1", + "sha256:1c9c13077560b8c0404c38d8e385d9e171aa8aec2a9b3139ded315a4c5ffc4d8", + "sha256:26f70a009c70866a07c43e25d6d9a1fb027ecef110a6c93cc8aec04ddf2ad05f", + "sha256:335d2a6afdd3a31f4ef210b46e6824848491c969f4b3a655d1864f655d57c5d3", + "sha256:43dc3082f3a8fd5bb0c80df5a8ab96d81eafeca701615aaa0b01910b1869e678", + "sha256:44a7e0e117032666d37bcfa42161c7eb27c6ed9100d260e5b25751a6d8d7a2e8", + "sha256:4c4ecf20e054716cc1e5a81cadc44d3f4027108d8dd0861d8b1e3bd7a32d4f0a", + "sha256:5539547ba11f4affcdc4890cc85bfdd3f2d7186042d91e9340add98699cc3d50", + "sha256:6560b68e98aba17afa4e898aab21d06d549738267dbe4d0981a24b4c1db66368", + "sha256:6cf42bc495f7e3fd25e92912a22f47e439f3a809814103a1b727d373f758915a", + "sha256:b2e64d1695bcd0d916e8633ab12179bde8d96e8cbd18d9d0c3020409cfaf8091", + "sha256:b4967af248c1fde0b184d81b2aa9646d96a400342d26f837e772a1dcb11cdc10", + "sha256:c1347a0d6e90d4a0fd67514c8691346c5cd1ee6039415eba97690f4b5d594915", + "sha256:c62045146474c41c5b9e4c758873b3b2872b3e0fefd2b87de3f08292c370fce6", + "sha256:c64c9972a847b5de9a47f5e3a06b280ee3301ac83089cc9d7ea922f7cea5954c", + "sha256:cf669980df3a6db918e69920df3eaf52901aa4c007287070a8b6e0da811cd2a2", + "sha256:e95f107de632ae6effa6915f194f2c282db592b9aa449070a5f9c065c478ec47", + "sha256:ec0d482b9d28c123a2c6ccfa5341d47734b1dee2d61a655a99f26ef9c0080ce7", + "sha256:ec7b08ffefae94b2c0a85df4ec17e3ada8f9f2bfae18e8b6812ece366917d0c5", + "sha256:ef822f66d932a7ced43844a4684d7bd24c4cc7ebe8030ee7277cf7c033e58a13" + ], + "version": "==3.13.2" + }, + "yorm": { + "hashes": [ + "sha256:a5735bb1cbd4ef79abbed2eee257563d108fa23abcb4d57ee1dc59236c04c727", + "sha256:f1368e4a9430fefcaf9abe8a59fc9db3873889ef518d3706ce619c79f31b2b5a" + ], + "version": "==1.5.1" + } + }, "develop": { + "altgraph": { + "hashes": [ + "sha256:49dc134049903cc73fb76ca3cc9bef5b2b8c01c28732dd29594f99af2b449fc5", + "sha256:fc28b986a68fde8d3ff0e6d6ba3fbdd2cd562d11d45ef7c7735fbd826c9eec2e" + ], + "version": "==0.15" + }, "astroid": { "hashes": [ "sha256:a92c1197dd496ef2470e73e1c296fc02a719907ee07259744e26a13bda9d4862", @@ -138,6 +208,12 @@ "index": "pypi", "version": "==0.3.10" }, + "future": { + "hashes": [ + "sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb" + ], + "version": "==0.16.0" + }, "idna": { "hashes": [ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", @@ -201,6 +277,21 @@ ], "version": "==2.5.1" }, + "macfsevents": { + "hashes": [ + "sha256:1324b66b356051de662ba87d84f73ada062acd42b047ed1246e60a449f833e10" + ], + "index": "pypi", + "markers": "sys_platform == 'darwin'", + "version": "==0.8.1" + }, + "macholib": { + "hashes": [ + "sha256:7f76a7ef4f58f85889dec25fb532bad5acfd461c444738dfeb2e7bf855d5906b", + "sha256:9aeec52d7da59912b15445d08b08d95cee48414f01dd035be06f04a825973c08" + ], + "version": "==1.9" + }, "markdown": { "hashes": [ "sha256:9ba587db9daee7ec761cfc656272be6aabe2ed300fece21208e4aab2e457bc8f", @@ -245,6 +336,12 @@ ], "version": "==1.3.7" }, + "pefile": { + "hashes": [ + "sha256:675c35ee0e1677db9e80d2f48d8a7ff2cf38e6207e8cd5e2a2c6d126db025854" + ], + "version": "==2017.11.5" + }, "pkginfo": { "hashes": [ "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", @@ -290,6 +387,13 @@ "index": "pypi", "version": "==2.2.0" }, + "pyinstaller": { + "hashes": [ + "sha256:715f81f24b1ef0e5fe3b3c71e7540551838e46e9de30882aa7c0a521147fd1ce" + ], + "index": "pypi", + "version": "==3.3.1" + }, "pylint": { "hashes": [ "sha256:34ab1a62fbdd48059d082f5a52b7e719a39b757a53ecbf0b2b7169b9c6a2cc28", @@ -298,6 +402,14 @@ "index": "pypi", "version": "==1.8.3" }, + "pync": { + "hashes": [ + "sha256:85737aab9fc69cf59dc9fe831adbe94ac224944c05e297c98de3c2413f253530" + ], + "index": "pypi", + "markers": "sys_platform == 'darwin'", + "version": "==1.6.1" + }, "pytest": { "hashes": [ "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", @@ -439,11 +551,11 @@ }, "wheel": { "hashes": [ - "sha256:9515fe0a94e823fd90b08d22de45d7bde57c90edce705b22f5e1ecf7e1b653c8", - "sha256:e721e53864f084f956f40f96124a74da0631ac13fbbd1ba99e8e2b5e9cafdf64" + "sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce", + "sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107" ], "index": "pypi", - "version": "==0.30.0" + "version": "==0.31.0" }, "wrapt": { "hashes": [ diff --git a/bin/verchew b/bin/verchew index b717cf68..3cd8c5c1 100755 --- a/bin/verchew +++ b/bin/verchew @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # The MIT License (MIT) -# Copyright © 2017, Jace Browning +# Copyright © 2016, Jace Browning # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -40,34 +40,37 @@ from collections import OrderedDict from subprocess import Popen, PIPE, STDOUT import logging -__version__ = '1.2' +__version__ = '1.3' PY2 = sys.version_info[0] == 2 -CONFIG_FILENAMES = ['.verchew.ini', 'verchew.ini', '.verchew', '.verchewrc'] +CONFIG_FILENAMES = [ + 'verchew.ini', + '.verchew.ini', + '.verchewrc', + '.verchew', +] SAMPLE_CONFIG = """ -[Make] +[Python] -cli = make -version = GNU Make -message = +cli = python +versions = Python 3.5 | Python 3.6 -[Python 2] +[Legacy Python] cli = python2 -version = Python 2.7. -message = +version = Python 2.7 [virtualenv] cli = virtualenv version = 15. -message = +message = Only required with Python 2. -[Python 3] +[Make] -cli = python -version = Python 3. -message = +cli = make +version = GNU Make +optional = true """.strip() STYLE = { @@ -177,6 +180,11 @@ def parse_config(path): for name, value in config.items(section): data[section][name] = value + for name in data: + versions = data[name].get('versions', data[name].pop('version', "")) + data[name]['versions'] = versions + data[name]['patterns'] = [v.strip() for v in versions.split('|')] + return data @@ -186,15 +194,18 @@ def check_dependencies(config): for name, settings in config.items(): show("Checking for {0}...".format(name), head=True) output = get_version(settings['cli'], settings.get('cli_version_arg')) - if match_version(settings['version'], output): - show(_("~") + " MATCHED: {0}".format(settings['version'])) - success.append(_("~")) + + for pattern in settings['patterns']: + if match_version(pattern, output): + show(_("~") + " MATCHED: {0}".format(pattern)) + success.append(_("~")) + break else: if settings.get('optional'): - show(_("?") + " EXPECTED: {0}".format(settings['version'])) + show(_("?") + " EXPECTED: {0}".format(settings['versions'])) success.append(_("?")) else: - show(_("x") + " EXPECTED: {0}".format(settings['version'])) + show(_("x") + " EXPECTED: {0}".format(settings['versions'])) success.append(_("x")) if settings.get('message'): show(_("*") + " MESSAGE: {0}".format(settings['message'])) diff --git a/gitman.yml b/gitman.yml index 1e30d32b..5bb23897 100644 --- a/gitman.yml +++ b/gitman.yml @@ -65,7 +65,7 @@ sources_locked: repo: https://github.com/jacebrowning/gitman-demo sparse_paths: - - rev: ddbe17ef173538d1fda29bd99a14bab3c5d86e78 + rev: f50c1ac8bf27377625b0cc93ea27f8069c7b513a link: scripts: - diff --git a/scent.py b/scent.py index c9f31239..4e813eab 100644 --- a/scent.py +++ b/scent.py @@ -25,7 +25,7 @@ class Options(object): (('make', 'test-unit', 'DISABLE_COVERAGE=true'), "Unit Tests", True), (('make', 'test-all'), "Integration Tests", False), (('make', 'check'), "Static Analysis", True), - (('make', 'doc'), None, True), + (('make', 'docs'), None, True), ] diff --git a/setup.py b/setup.py index 271f402f..2f51daba 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,7 @@ #!/usr/bin/env python -"""Setup script for the package.""" - import os import sys -import logging import setuptools @@ -27,8 +24,7 @@ def read_package_variable(key, filename='__init__.py'): parts = line.strip().split(' ', 2) if parts[:-1] == [key, '=']: return parts[-1].strip("'") - logging.warning("'%s' not found in '%s'", key, module_path) - return None + sys.exit("'%s' not found in '%s'", key, module_path) def build_description():