diff --git a/.appveyor.yml b/.appveyor.yml index 32138abf..cc1c35a9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,15 +2,13 @@ environment: global: RANDOM_SEED: 0 matrix: - - PYTHON_MAJOR: 3 - PYTHON_MINOR: 5 - PYTHON_MAJOR: 3 PYTHON_MINOR: 6 - PYTHON_MAJOR: 3 PYTHON_MINOR: 7 cache: - - .venv -> Pipfile.lock + - .venv -> Makefile install: # Add Make and Python to the PATH @@ -19,7 +17,8 @@ install: - set PATH=C:\Python%PYTHON_MAJOR%%PYTHON_MINOR%;%PATH% - set PATH=C:\Python%PYTHON_MAJOR%%PYTHON_MINOR%\Scripts;%PATH% # Install system dependencies - - pip install pipenv + - curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python + - set PATH=%USERPROFILE%\.poetry\bin;%PATH% - make doctor # Install project dependencies - make install diff --git a/.coveragerc b/.coveragerc index 5033e7f3..5aa119cc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,6 +2,15 @@ branch = true +data_file = .cache/coverage + omit = .venv/* */tests/* + */__main__.py + +[report] + +exclude_lines = + pragma: no cover + raise NotImplementedError diff --git a/.isort.cfg b/.isort.cfg index 361814db..55a392b7 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -2,12 +2,15 @@ not_skip = __init__.py -multi_line_output = 5 +multi_line_output = 3 +known_standard_library = dataclasses,typing_extensions known_third_party = click,log -known_first_party = demo +known_first_party = gitman combine_as_imports = true +force_grid_wrap = false include_trailing_comma = true lines_after_imports = 2 +line_length = 88 diff --git a/.mypy.ini b/.mypy.ini new file mode 100644 index 00000000..264105fe --- /dev/null +++ b/.mypy.ini @@ -0,0 +1,7 @@ +[mypy] + +ignore_missing_imports = true +no_implicit_optional = true +check_untyped_defs = true + +cache_dir = .cache/mypy/ diff --git a/.pycodestyle.ini b/.pycodestyle.ini deleted file mode 100644 index 16c85a65..00000000 --- a/.pycodestyle.ini +++ /dev/null @@ -1,9 +0,0 @@ -[pycodestyle] - -# W504 line break after binary operator -# E401 multiple imports on one line (checked by PyLint) -# E402 module level import not at top of file (checked by PyLint) -# E501 line too long (checked by PyLint) -# E711 comparison to None (used to improve test style) -# E712 comparison to True (used to improve test style) -ignore = W504,E401,E402,E501,E711,E712 diff --git a/.pylint.ini b/.pylint.ini index b38c6328..c915f699 100644 --- a/.pylint.ini +++ b/.pylint.ini @@ -127,6 +127,7 @@ disable= logging-not-lazy, redefined-builtin, too-many-public-methods, + bad-continuation, # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -270,7 +271,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=79 +max-line-length=88 # Maximum number of lines in a module max-module-lines=1000 @@ -315,7 +316,7 @@ ignore-docstrings=yes ignore-imports=no # Minimum lines number of a similarity. -min-similarity-lines=4 +min-similarity-lines=6 [SPELLING] diff --git a/.travis.yml b/.travis.yml index 03524e7c..8a080b1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - 3.5 - 3.6 matrix: include: @@ -11,14 +10,15 @@ matrix: cache: pip: true directories: - - .venv + - ${VIRTUAL_ENV} env: global: - RANDOM_SEED=0 before_install: - - pip install pipenv + - curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python + - source $HOME/.poetry/env - make doctor install: diff --git a/.verchew.ini b/.verchew.ini index ba9d09dc..a6eb2695 100644 --- a/.verchew.ini +++ b/.verchew.ini @@ -6,22 +6,22 @@ version = GNU Make [Python] cli = python -version = Python 3. +version = Python 3 -[pipenv] +[Poetry] -cli = pipenv -versions = 10. | 11. +cli = poetry +version = 0.12 [Git] cli = git -version = 2. +version = 2 [Graphviz] cli = dot cli_version_arg = -V -version = 2. +version = 2 optional = true message = This is only needed to generate UML diagrams for documentation. diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0b0c8f..7bc21f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,10 @@ -# Revision History - -## 1.6 (unreleased) +# 1.6 (unreleased) - Added `git svn` support. (@daniel-brosche) - Added `$GITMAN_CACHE_DISABLE` to disable repository mirrors. (@daniel-brosche) +- **BREAKING**: Dropped support for Python 3.5. -## 1.5 (2018-09-08) +# 1.5 (2018-09-08) - Added `--keep-location` option on `uninstall`. (@DavidWatkins) - Added feature to enable sparse checkouts. See the docs for further information. (@xenji) @@ -13,74 +12,74 @@ - **BREAKING**: Renamed `--no-lock` to `--skip-lock` on `update` command. - **BREAKING**: Renamed `--no-dirty` to `--fail-if-dirty` on `list` command. -## 1.4 (2017-03-21) +# 1.4 (2017-03-21) - Allow config files to exist in subdirectories of the main project. - Added `$GITMAN_CACHE` to customize the repository cache location. -## 1.3 (2017-02-03) +# 1.3 (2017-02-03) - Added `init` command to generate sample config files. - Added support for post-install scripts on dependencies. - Updated config format to support `null` for links. -## 1.2 (2017-01-08) +# 1.2 (2017-01-08) - Added preliminary Windows support. (@StudioEtrange) -## 1.1 (2017-01-06) +# 1.1 (2017-01-06) - Added coloring to the command-line output. - Fixed issue where `` could be saved as a locked revision. -## 1.0.2 (2016-07-28) +# 1.0.2 (2016-07-28) - Moved documentation to http://gitman.readthedocs.io/. -## 1.0.1 (2016-05-31) +# 1.0.1 (2016-05-31) - Replaced calls to `git remote add origin` with `git remote set-url origin`. -## 1.0 (2016-05-22) +# 1.0 (2016-05-22) - Initial stable release. -## 0.11 (2016-05-10) +# 0.11 (2016-05-10) - Removed dependency on `sh` to support Cygwin/MinGW/etc. on Windows. - Dropped Python 3.4 support for `subprocess` and `*args` improvements. - **BREAKING**: Renamed config file key `dir` to `name`. -## 0.10 (2016-04-14) +# 0.10 (2016-04-14) - Added `show` command to display dependency and internal paths. -## 0.9 (2016-03-31) +# 0.9 (2016-03-31) - Added `edit` command to launch the config file. - Depth now defaults to 5 to prevent infinite recursion. - Fixed handling of source lists containing different dependencies. -## 0.8.3 (2016-03-14) +# 0.8.3 (2016-03-14) - Renamed to GitMan. -## 0.8.2 (2016-02-24) +# 0.8.2 (2016-02-24) - Updated to YORM v0.6. -## 0.8.1 (2016-01-21) +# 0.8.1 (2016-01-21) - Added an error message when attempting to lock invalid repositories. -## 0.8 (2016-01-13) +# 0.8 (2016-01-13) - Switched to using repository mirrors to speed up cloning. - Disabled automatic fetching on install. - Added `--fetch` option on `install` to always fetch. - Now displaying `git status` output when there are changes. -## 0.7 (2015-12-22) +# 0.7 (2015-12-22) - Fixed `git remote rm` command. (@hdnivara) - Now applying the `update` dependency filter to locking as well. @@ -88,12 +87,12 @@ - Added `lock` command to manually save all dependency versions. - Now requiring `--lock` option on `update` to explicitly lock dependencies. -## 0.6 (2015-11-13) +# 0.6 (2015-11-13) - Added the ability to filter the dependency list on `install` and `update`. - Added `--depth` option to limit dependency traversal on `install`, `update`, and `list`. -## 0.5 (2015-10-20) +# 0.5 (2015-10-20) - Added Git plugin support via: `git deps`. - Removed `--no-clean` option (now the default) on `install` and `update`. @@ -103,15 +102,15 @@ - Disabled warnings when running `install` without locked sources. - Added `--no-lock` option to disable version recording. -## 0.4.2 (2015-10-18) +# 0.4.2 (2015-10-18) - Fixed crash when running with some sources missing. -## 0.4.1 (2015-09-24) +# 0.4.1 (2015-09-24) - Switched to cloning for initial working tree creation. -## 0.4 (2015-09-18) +# 0.4 (2015-09-18) - Replaced `install` command with `update`. - Updated `install` command to use locked dependency versions. @@ -119,55 +118,55 @@ - Now requiring `--force` to `uninstall` with uncommitted changes. - Updated `list` command to show full shell commands. -## 0.3.1 (2015-09-09) +# 0.3.1 (2015-09-09) - Ensures files are not needlessly reloaded with newer versions of YORM. -## 0.3 (2015-06-26) +# 0.3 (2015-06-26) - Added `--no-clean` option to disable removing untracked files. - Added support for `rev-parse` dates as the dependency `rev`. -## 0.2.5 (2015-06-15) +# 0.2.5 (2015-06-15) - Added `--quiet` option to hide warnings. -## 0.2.4 (2015-05-19) +# 0.2.4 (2015-05-19) - Now hiding YORM logging bellow warnings. -## 0.2.3 (2015-05-17) +# 0.2.3 (2015-05-17) - Upgraded to YORM v0.4. -## 0.2.2 (2015-05-04) +# 0.2.2 (2015-05-04) - Specified YORM < v0.4. -## 0.2.1 (2015-03-12) +# 0.2.1 (2015-03-12) - Added automatic remote branch tracking in dependencies. - Now requiring `--force` when there are untracked files. -## 0.2 (2015-03-10) +# 0.2 (2015-03-10) - Added `list` command to display current URLs/SHAs. -## 0.1.4 (2014-02-27) +# 0.1.4 (2014-02-27) - Fixed an outdated index when checking for changes. -## 0.1.3 (2014-02-27) +# 0.1.3 (2014-02-27) - Fixed extra whitespace when logging shell output. -## 0.1.2 (2014-02-27) +# 0.1.2 (2014-02-27) - Added `--force` argument to: - overwrite uncommitted changes - create symbolic links in place of directories - Added live shell command output with `-vv` argument. -## 0.1 (2014-02-24) +# 0.1 (2014-02-24) - Initial release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 19feb0de..94a3eb00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,15 +1,13 @@ -# For Contributors +# Setup -## Setup - -### Requirements +## Requirements * Make: * Windows: http://mingw.org/download/installer * Mac: http://developer.apple.com/xcode * Linux: http://www.gnu.org/software/make -* pipenv: http://docs.pipenv.org -* Pandoc: http://johnmacfarlane.net/pandoc/installing.html +* Python: `$ pyenv install` +* Poetry: https://poetry.eustace.io/docs/#installation * Graphviz: http://www.graphviz.org/Download.php To confirm these system dependencies are configured correctly: @@ -18,7 +16,7 @@ To confirm these system dependencies are configured correctly: $ make doctor ``` -### Installation +## Installation Install project dependencies into a virtual environment: @@ -26,44 +24,39 @@ Install project dependencies into a virtual environment: $ make install ``` -## Development Tasks +# Development Tasks -### Testing +## Manual -Manually run the tests: +Run the tests: ```sh $ make test ``` -or keep them running on change: +Run static analysis: ```sh -$ make watch +$ make check ``` -> In order to have OS X notifications, `brew install terminal-notifier`. - -### Documentation - Build the documentation: ```sh $ make docs ``` -### Static Analysis +## Automatic -Run linters and static analyzers: +Keep all of the above tasks running on change: ```sh -$ make pylint -$ make pycodestyle -$ make pydocstyle -$ make check # includes all checks +$ make watch ``` -## Continuous Integration +> In order to have OS X notifications, `brew install terminal-notifier`. + +# Continuous Integration The CI server will report overall build status: @@ -71,7 +64,7 @@ The CI server will report overall build status: $ make ci ``` -## Release Tasks +# Release Tasks Release to PyPI: diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 855deca1..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -include *.rst *.txt *.md -recursive-include docs *.rst *.txt *.md -graft */files -graft */*/files diff --git a/Makefile b/Makefile index 4ecc29b1..aa87433f 100644 --- a/Makefile +++ b/Makefile @@ -9,32 +9,27 @@ CONFIG := $(wildcard *.py) MODULES := $(wildcard $(PACKAGE)/*.py) # Virtual environment paths -export PIPENV_VENV_IN_PROJECT=true -export PIPENV_IGNORE_VIRTUALENVS=true -VENV := .venv +VIRTUAL_ENV ?= .venv # MAIN TASKS ################################################################## -SNIFFER := pipenv run sniffer - .PHONY: all all: install .PHONY: ci -ci: check test demo ## Run all tasks that determine CI status +ci: format check test mkdocs ## Run all tasks that determine CI status .PHONY: watch watch: install .clean-test ## Continuously run all CI tasks when files chanage - $(SNIFFER) + poetry run sniffer .PHONY: demo demo: install - pipenv run python setup.py develop - pipenv run gitman install --force # some scripts have intentional errors - pipenv run gitman update --force # some scripts have intentional errors - pipenv run gitman list - pipenv run gitman lock - pipenv run gitman uninstall + poetry run gitman install --force # some scripts have intentional errors + poetry run gitman update --force # some scripts have intentional errors + poetry run gitman list + poetry run gitman lock + poetry run gitman uninstall # SYSTEM DEPENDENCIES ######################################################### @@ -44,48 +39,42 @@ doctor: ## Confirm system dependencies are available # PROJECT DEPENDENCIES ######################################################## -DEPENDENCIES = $(VENV)/.pipenv-$(shell bin/checksum Pipfile* setup.py) +DEPENDENCIES := $(VIRTUAL_ENV)/.poetry-$(shell bin/checksum pyproject.toml poetry.lock) .PHONY: install -install: $(DEPENDENCIES) +install: $(DEPENDENCIES) .cache -$(DEPENDENCIES): - pipenv run python setup.py develop - pipenv install --dev +$(DEPENDENCIES): poetry.lock + @ poetry config settings.virtualenvs.in-project true + poetry install @ touch $@ -# CHECKS ###################################################################### - -ISORT := pipenv run isort -PYLINT := pipenv run pylint -PYCODESTYLE := pipenv run pycodestyle -PYDOCSTYLE := pipenv run pydocstyle - -.PHONY: check -check: isort pylint pycodestyle pydocstyle ## Run linters and static analysis +poetry.lock: pyproject.toml + poetry lock + @ touch $@ -.PHONY: isort -isort: install - $(ISORT) $(PACKAGES) $(CONFIG) --recursive --apply +.cache: + @ mkdir -p .cache -.PHONY: pylint -pylint: install - $(PYLINT) $(PACKAGES) $(CONFIG) --rcfile=.pylint.ini +# CHECKS ###################################################################### -.PHONY: pycodestyle -pycodestyle: install - $(PYCODESTYLE) $(PACKAGES) $(CONFIG) --config=.pycodestyle.ini +.PHONY: format +format: install + poetry run isort $(PACKAGES) --recursive --apply + poetry run black $(PACKAGES) + @ echo -.PHONY: pydocstyle -pydocstyle: install - $(PYDOCSTYLE) $(PACKAGES) $(CONFIG) +.PHONY: check +check: install format ## Run formaters, linters, and static analysis +ifdef CI + git diff --exit-code +endif + poetry run pylint $(PACKAGES) --rcfile=.pylint.ini + poetry run mypy $(PACKAGES) --config-file=.mypy.ini + poetry run pydocstyle $(PACKAGES) $(CONFIG) # TESTS ####################################################################### -PYTEST := pipenv run pytest -COVERAGE := pipenv run coverage -COVERAGE_SPACE := pipenv run coveragespace - RANDOM_SEED ?= $(shell date +%s) FAILURES := .cache/v/cache/lastfailed @@ -101,23 +90,23 @@ test: test-all ## Run unit and integration tests .PHONY: test-unit test-unit: install @ ( mv $(FAILURES) $(FAILURES).bak || true ) > /dev/null 2>&1 - $(PYTEST) $(PACKAGE) $(PYTEST_OPTIONS) + poetry run pytest $(PACKAGE) $(PYTEST_OPTIONS) @ ( mv $(FAILURES).bak $(FAILURES) || true ) > /dev/null 2>&1 - $(COVERAGE_SPACE) $(REPOSITORY) unit + poetry run coveragespace $(REPOSITORY) unit .PHONY: test-int test-int: install - @ if test -e $(FAILURES); then TEST_INTEGRATION=true $(PYTEST) tests $(PYTEST_RERUN_OPTIONS); fi + @ if test -e $(FAILURES); then TEST_INTEGRATION=true poetry run pytest tests $(PYTEST_RERUN_OPTIONS); fi @ rm -rf $(FAILURES) - TEST_INTEGRATION=true $(PYTEST) tests $(PYTEST_OPTIONS) - $(COVERAGE_SPACE) $(REPOSITORY) integration + TEST_INTEGRATION=true poetry run pytest tests $(PYTEST_OPTIONS) + poetry run coveragespace $(REPOSITORY) integration .PHONY: test-all test-all: install - @ if test -e $(FAILURES); then TEST_INTEGRATION=true $(PYTEST) $(PACKAGES) $(PYTEST_RERUN_OPTIONS); fi + @ if test -e $(FAILURES); then TEST_INTEGRATION=true poetry run pytest $(PACKAGES) $(PYTEST_RERUN_OPTIONS); fi @ rm -rf $(FAILURES) - TEST_INTEGRATION=true $(PYTEST) $(PACKAGES) $(PYTEST_OPTIONS) - $(COVERAGE_SPACE) $(REPOSITORY) overall + TEST_INTEGRATION=true poetry run pytest $(PACKAGES) $(PYTEST_OPTIONS) + poetry run coveragespace $(REPOSITORY) overall .PHONY: read-coverage read-coverage: @@ -125,82 +114,59 @@ read-coverage: # DOCUMENTATION ############################################################### -PYREVERSE := pipenv run pyreverse -MKDOCS := pipenv run mkdocs - MKDOCS_INDEX := site/index.html .PHONY: docs -docs: uml mkdocs ## Generate documentation - -.PHONY: docs/demo.gif -docs/demo.gif: - @ sleep 3; clear; sleep 1 - gitman install --force - @ sleep 3; clear; sleep 1 - gitman list - @ sleep 3; clear; sleep 1 - gitman lock - @ sleep 3; clear; sleep 1 - gitman uninstall +docs: mkdocs uml ## Generate documentation and UML + +.PHONY: mkdocs +mkdocs: install $(MKDOCS_INDEX) +$(MKDOCS_INDEX): mkdocs.yml docs/*.md + @ mkdir -p docs/about + @ cd docs && ln -sf ../README.md index.md + @ cd docs/about && ln -sf ../../CHANGELOG.md changelog.md + @ cd docs/about && ln -sf ../../CONTRIBUTING.md contributing.md + @ cd docs/about && ln -sf ../../LICENSE.md license.md + poetry run mkdocs build --clean --strict .PHONY: uml uml: install docs/*.png docs/*.png: $(MODULES) - $(PYREVERSE) $(PACKAGE) -p $(PACKAGE) -a 1 -f ALL -o png --ignore tests + poetry run pyreverse $(PACKAGE) -p $(PACKAGE) -a 1 -f ALL -o png --ignore tests - mv -f classes_$(PACKAGE).png docs/classes.png - mv -f packages_$(PACKAGE).png docs/packages.png -.PHONY: mkdocs -mkdocs: install $(MKDOCS_INDEX) -$(MKDOCS_INDEX): mkdocs.yml docs/*.md - ln -sf `realpath README.md --relative-to=docs` docs/index.md - ln -sf `realpath CHANGELOG.md --relative-to=docs/about` docs/about/changelog.md - ln -sf `realpath CONTRIBUTING.md --relative-to=docs/about` docs/about/contributing.md - ln -sf `realpath LICENSE.md --relative-to=docs/about` docs/about/license.md - $(MKDOCS) build --clean --strict - .PHONY: mkdocs-live mkdocs-live: mkdocs eval "sleep 3; bin/open http://127.0.0.1:8000" & - $(MKDOCS) serve + poetry run mkdocs serve # BUILD ####################################################################### -PYINSTALLER := pipenv run pyinstaller -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) +$(DIST_FILES): $(MODULES) pyproject.toml rm -f $(DIST_FILES) - pipenv run python setup.py check --strict --metadata - pipenv run python setup.py sdist - pipenv run python setup.py bdist_wheel + poetry build .PHONY: exe exe: install $(EXE_FILES) $(EXE_FILES): $(MODULES) $(PROJECT).spec # For framework/shared support: https://github.com/yyuu/pyenv/wiki - $(PYINSTALLER) $(PROJECT).spec --noconfirm --clean + poetry run pyinstaller $(PROJECT).spec --noconfirm --clean $(PROJECT).spec: - $(PYINSTALLER_MAKESPEC) $(PACKAGE)/__main__.py --onefile --windowed --name=$(PROJECT) + poetry run pyi-makespec $(PACKAGE)/__main__.py --onefile --windowed --name=$(PROJECT) # RELEASE ##################################################################### -TWINE := pipenv run twine - .PHONY: upload upload: dist ## Upload the current version to PyPI git diff --name-only --exit-code - $(TWINE) upload dist/*.* + poetry publish bin/open https://pypi.org/project/$(PROJECT) # CLEANUP ##################################################################### @@ -210,21 +176,20 @@ clean: .clean-build .clean-docs .clean-test .clean-install ## Delete all generat .PHONY: clean-all clean-all: clean - rm -rf $(VENV) + rm -rf $(VIRTUAL_ENV) .PHONY: .clean-install .clean-install: - find $(PACKAGES) -name '*.pyc' -delete find $(PACKAGES) -name '__pycache__' -delete rm -rf *.egg-info .PHONY: .clean-test .clean-test: - rm -rf .cache .pytest .coverage htmlcov xmlreport + rm -rf .cache .pytest .coverage htmlcov .PHONY: .clean-docs .clean-docs: - rm -rf *.rst docs/apidocs *.html docs/*.png site + rm -rf docs/*.png site .PHONY: .clean-build .clean-build: diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 69819930..00000000 --- a/Pipfile +++ /dev/null @@ -1,49 +0,0 @@ -[[source]] - -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[requires] - -python_version = "3" - -[packages] - -gitman = { path = ".", editable = true } - -[dev-packages] - -# Linters -pylint = "~=2.1" -pycodestyle = "~=2.3" -pydocstyle = "~=2.0" - -# Testing -pytest = "~=3.3" -pytest-describe = "*" -pytest-expecter = "*" -pytest-random = "*" -pytest-cov = "*" -pathlib2 = "*" -freezegun = "*" - -# Reports -coveragespace = "*" - -# Documentation -mkdocs = "<1" -docutils = "*" -pygments = "*" - -# Build -wheel = "*" -pyinstaller = "*" - -# Release -twine = "*" - -# Tooling -sniffer = "*" -MacFSEvents = { version = "*", sys_platform = "== 'darwin'" } -pync = { version = "*", sys_platform = "== 'darwin'" } diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 69db1562..00000000 --- a/Pipfile.lock +++ /dev/null @@ -1,642 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "1614acf2333a1b4dc5ba33c941998436cee08ae89b051946ad13206b10e57778" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "gitman": { - "editable": true, - "path": "." - }, - "parse": { - "hashes": [ - "sha256:c3cdf6206f22aeebfa00e5b954fcfea13d1b2dc271c75806b6025b94fb490939" - ], - "version": "==1.8.4" - }, - "pyyaml": { - "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" - ], - "version": "==3.13" - }, - "simplejson": { - "hashes": [ - "sha256:067a7177ddfa32e1483ba5169ebea1bc2ea27f224853211ca669325648ca5642", - "sha256:2fc546e6af49fb45b93bbe878dea4c48edc34083729c0abd09981fe55bdf7f91", - "sha256:354fa32b02885e6dae925f1b5bbf842c333c1e11ea5453ddd67309dc31fdb40a", - "sha256:37e685986cf6f8144607f90340cff72d36acf654f3653a6c47b84c5c38d00df7", - "sha256:3af610ee72efbe644e19d5eaad575c73fb83026192114e5f6719f4901097fce2", - "sha256:3b919fc9cf508f13b929a9b274c40786036b31ad28657819b3b9ba44ba651f50", - "sha256:3dd289368bbd064974d9a5961101f080e939cbe051e6689a193c99fb6e9ac89b", - "sha256:6c3258ffff58712818a233b9737fe4be943d306c40cf63d14ddc82ba563f483a", - "sha256:75e3f0b12c28945c08f54350d91e624f8dd580ab74fd4f1bbea54bc6b0165610", - "sha256:b1f329139ba647a9548aa05fb95d046b4a677643070dc2afc05fa2e975d09ca5", - "sha256:ee9625fc8ee164902dfbb0ff932b26df112da9f871c32f0f9c1bcf20c350fe2a", - "sha256:fb2530b53c28f0d4d84990e945c2ebb470edb469d63e389bf02ff409012fe7c5" - ], - "version": "==3.16.0" - }, - "yorm": { - "hashes": [ - "sha256:863674ad8e1cfe5b8aa42e333039c0f54d591bb0d28ff9d4299b8109a02239f9", - "sha256:aa540ccb087a9c3a8eac385073a2da1c5362591b45dec7a9a2cb212e898d9f84" - ], - "version": "==1.6" - } - }, - "develop": { - "altgraph": { - "hashes": [ - "sha256:d6814989f242b2b43025cba7161fc1b8fb487a62cd49c49245d6fd01c18ac997", - "sha256:ddf5320017147ba7b810198e0b6619bd7b5563aa034da388cea8546b877f9b0c" - ], - "version": "==0.16.1" - }, - "astroid": { - "hashes": [ - "sha256:292fa429e69d60e4161e7612cb7cc8fa3609e2e309f80c224d93a76d5e7b58be", - "sha256:c7013d119ec95eb626f7a2011f0b63d0c9a095df9ad06d8507b37084eada1a8d" - ], - "version": "==2.0.4" - }, - "atomicwrites": { - "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" - ], - "version": "==1.2.1" - }, - "attrs": { - "hashes": [ - "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", - "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" - ], - "version": "==18.2.0" - }, - "backports.shutil-get-terminal-size": { - "hashes": [ - "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", - "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" - ], - "version": "==1.0.0" - }, - "bleach": { - "hashes": [ - "sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718", - "sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9" - ], - "version": "==3.0.2" - }, - "certifi": { - "hashes": [ - "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", - "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" - ], - "version": "==2018.10.15" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "click": { - "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" - ], - "version": "==7.0" - }, - "colorama": { - "hashes": [ - "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", - "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" - ], - "version": "==0.3.9" - }, - "coverage": { - "hashes": [ - "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", - "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", - "sha256:0bf8cbbd71adfff0ef1f3a1531e6402d13b7b01ac50a79c97ca15f030dba6306", - "sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95", - "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", - "sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd", - "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", - "sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1", - "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", - "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", - "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", - "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", - "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", - "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", - "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", - "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", - "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", - "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", - "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", - "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", - "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", - "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", - "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", - "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", - "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", - "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", - "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", - "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", - "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", - "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", - "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", - "sha256:f05a636b4564104120111800021a92e43397bc12a5c72fed7036be8556e0029e", - "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" - ], - "version": "==4.5.1" - }, - "coveragespace": { - "hashes": [ - "sha256:498b54ec158a19e1f5647da681dc77fd9d17df11ecff1253d60ac7970209f6e5", - "sha256:7c5ce4641e0f995b9be0e8b53401fd7b6d17db1b8c23bfd06f0c845ad0de5b5f" - ], - "index": "pypi", - "version": "==2.1" - }, - "docopt": { - "hashes": [ - "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" - ], - "version": "==0.6.2" - }, - "docutils": { - "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" - ], - "index": "pypi", - "version": "==0.14" - }, - "freezegun": { - "hashes": [ - "sha256:6cb82b276f83f2acce67f121dc2656f4df26c71e32238334eb071170b892a278", - "sha256:e839b43bfbe8158b4d62bb97e6313d39f3586daf48e1314fb1083d2ef17700da" - ], - "index": "pypi", - "version": "==0.3.11" - }, - "future": { - "hashes": [ - "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8" - ], - "version": "==0.17.1" - }, - "idna": { - "hashes": [ - "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", - "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" - ], - "version": "==2.7" - }, - "isort": { - "hashes": [ - "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", - "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", - "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" - ], - "version": "==4.3.4" - }, - "jinja2": { - "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" - ], - "version": "==2.10" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", - "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", - "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", - "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", - "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", - "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", - "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", - "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", - "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", - "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", - "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", - "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", - "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", - "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", - "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", - "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", - "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", - "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", - "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", - "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", - "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", - "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", - "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", - "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", - "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", - "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", - "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", - "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", - "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" - ], - "version": "==1.3.1" - }, - "livereload": { - "hashes": [ - "sha256:583179dc8d49b040a9da79bd33de59e160d2a8802b939e304eb359a4419f6498", - "sha256:dd4469a8f5a6833576e9f5433f1439c306de15dbbfeceabd32479b1123380fa5" - ], - "version": "==2.5.2" - }, - "macfsevents": { - "hashes": [ - "sha256:1324b66b356051de662ba87d84f73ada062acd42b047ed1246e60a449f833e10" - ], - "index": "pypi", - "markers": "sys_platform == 'darwin'", - "version": "==0.8.1" - }, - "macholib": { - "hashes": [ - "sha256:ac02d29898cf66f27510d8f39e9112ae00590adb4a48ec57b25028d6962b1ae1", - "sha256:c4180ffc6f909bf8db6cd81cff4b6f601d575568f4d5dee148c830e9851eb9db" - ], - "version": "==1.11" - }, - "markdown": { - "hashes": [ - "sha256:c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa", - "sha256:d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c" - ], - "version": "==3.0.1" - }, - "markupsafe": { - "hashes": [ - "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", - "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", - "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", - "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", - "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", - "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", - "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", - "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", - "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", - "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", - "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", - "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", - "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", - "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", - "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", - "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", - "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", - "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", - "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", - "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", - "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", - "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", - "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", - "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", - "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", - "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", - "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", - "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" - ], - "version": "==1.1.0" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mkdocs": { - "hashes": [ - "sha256:1b4d46cd1cb517cd743358da96a3efc588fd86f81512fb9c28214597b6dc731f", - "sha256:cd7264ea42d76f5bc1a0bd8b0a2c6c6e6be3a8742f5e78f47104a452dbe93600" - ], - "index": "pypi", - "version": "==0.17.5" - }, - "more-itertools": { - "hashes": [ - "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", - "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", - "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" - ], - "version": "==4.3.0" - }, - "nose": { - "hashes": [ - "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", - "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", - "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" - ], - "version": "==1.3.7" - }, - "pathlib2": { - "hashes": [ - "sha256:8eb170f8d0d61825e09a95b38be068299ddeda82f35e96c3301a8a5e7604cb83", - "sha256:d1aa2a11ba7b8f7b21ab852b1fb5afb277e1bb99d5dfc663380b5015c0d80c5a" - ], - "index": "pypi", - "version": "==2.3.2" - }, - "pefile": { - "hashes": [ - "sha256:4c5b7e2de0c8cb6c504592167acf83115cbbde01fe4a507c16a1422850e86cd6" - ], - "version": "==2018.8.8" - }, - "pkginfo": { - "hashes": [ - "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", - "sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee" - ], - "version": "==1.4.2" - }, - "pluggy": { - "hashes": [ - "sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095", - "sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f" - ], - "version": "==0.8.0" - }, - "py": { - "hashes": [ - "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", - "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" - ], - "version": "==1.7.0" - }, - "pycodestyle": { - "hashes": [ - "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", - "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" - ], - "index": "pypi", - "version": "==2.4.0" - }, - "pydocstyle": { - "hashes": [ - "sha256:08a870edc94508264ed90510db466c6357c7192e0e866561d740624a8fc7d90c", - "sha256:4d5bcde961107873bae621f3d580c3e35a426d3687ffc6f8fb356f6628da5a97", - "sha256:af9fcccb303899b83bec82dc9a1d56c60fc369973223a5e80c3dfa9bdf984405" - ], - "index": "pypi", - "version": "==2.1.1" - }, - "pygments": { - "hashes": [ - "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", - "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" - ], - "index": "pypi", - "version": "==2.2.0" - }, - "pyinstaller": { - "hashes": [ - "sha256:a5a6e04a66abfcf8761e89a2ebad937919c6be33a7b8963e1a961b55cb35986b" - ], - "index": "pypi", - "version": "==3.4" - }, - "pylint": { - "hashes": [ - "sha256:1d6d3622c94b4887115fe5204982eee66fdd8a951cf98635ee5caee6ec98c3ec", - "sha256:31142f764d2a7cd41df5196f9933b12b7ee55e73ef12204b648ad7e556c119fb" - ], - "index": "pypi", - "version": "==2.1.1" - }, - "pync": { - "hashes": [ - "sha256:38b9e61735a3161f9211a5773c5f5ea698f36af4ff7f77fa03e8d1ff0caa117f" - ], - "index": "pypi", - "markers": "sys_platform == 'darwin'", - "version": "==2.0.3" - }, - "pytest": { - "hashes": [ - "sha256:630ff1dbe04f469ee78faa5660f712e58b953da7df22ea5d828c9012e134da43", - "sha256:a2b5232735dd0b736cbea9c0f09e5070d78fcaba2823a4f6f09d9a81bd19415c" - ], - "index": "pypi", - "version": "==3.10.0" - }, - "pytest-cov": { - "hashes": [ - "sha256:513c425e931a0344944f84ea47f3956be0e416d95acbd897a44970c8d926d5d7", - "sha256:e360f048b7dae3f2f2a9a4d067b2dd6b6a015d384d1577c994a43f3f7cbad762" - ], - "index": "pypi", - "version": "==2.6.0" - }, - "pytest-describe": { - "hashes": [ - "sha256:bd6be131452b7822c872735ffe53ce3931b3b80cbbad1647c2b482cc9ef3d00e" - ], - "index": "pypi", - "version": "==0.11.1" - }, - "pytest-expecter": { - "hashes": [ - "sha256:1c8e9ab98ddd576436b61a7ba61ea11cfa5a3fc6b00288ce9e91e9dd770daf19", - "sha256:27c93dfe87e2f4d28c525031be68d3f89457e3315241d97ee15f7689544e0e37" - ], - "index": "pypi", - "version": "==1.3" - }, - "pytest-random": { - "hashes": [ - "sha256:92f25db8c5d9ffc20d90b51997b914372d6955cb9cf1f6ead45b90514fc0eddd" - ], - "index": "pypi", - "version": "==0.2" - }, - "python-dateutil": { - "hashes": [ - "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" - ], - "version": "==2.7.5" - }, - "python-termstyle": { - "hashes": [ - "sha256:6faf42ba42f2826c38cf70dacb3ac51f248a418e48afc0e36593df11cf3ab1d2", - "sha256:f42a6bb16fbfc5e2c66d553e7ad46524ea833872f75ee5d827c15115fafc94e2" - ], - "version": "==0.1.10" - }, - "pyyaml": { - "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" - ], - "version": "==3.13" - }, - "readme-renderer": { - "hashes": [ - "sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", - "sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" - ], - "version": "==24.0" - }, - "requests": { - "hashes": [ - "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", - "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" - ], - "version": "==2.20.1" - }, - "requests-toolbelt": { - "hashes": [ - "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", - "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5" - ], - "version": "==0.8.0" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" - }, - "sniffer": { - "hashes": [ - "sha256:e8a0daa4c51dff3d00482b45dc9b978159100a8d5a7df327c28ed96586559970", - "sha256:e90c1ad4bd3c31a5fad8e03d45dfc83377b31420aa0779f17280c817ce0c9dd8" - ], - "index": "pypi", - "version": "==0.4.0" - }, - "snowballstemmer": { - "hashes": [ - "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", - "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" - ], - "version": "==1.2.1" - }, - "tornado": { - "hashes": [ - "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", - "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a", - "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e", - "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3", - "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a" - ], - "version": "==4.5.3" - }, - "tqdm": { - "hashes": [ - "sha256:3c4d4a5a41ef162dd61f1edb86b0e1c7859054ab656b2e7c7b77e7fbf6d9f392", - "sha256:5b4d5549984503050883bc126280b386f5f4ca87e6c023c5d015655ad75bdebb" - ], - "version": "==4.28.1" - }, - "twine": { - "hashes": [ - "sha256:7d89bc6acafb31d124e6e5b295ef26ac77030bf098960c2a4c4e058335827c5c", - "sha256:fad6f1251195f7ddd1460cb76d6ea106c93adb4e56c41e0da79658e56e547d2c" - ], - "index": "pypi", - "version": "==1.12.1" - }, - "typed-ast": { - "hashes": [ - "sha256:0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", - "sha256:10703d3cec8dcd9eef5a630a04056bbc898abc19bac5691612acba7d1325b66d", - "sha256:1f6c4bd0bdc0f14246fd41262df7dfc018d65bb05f6e16390b7ea26ca454a291", - "sha256:25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", - "sha256:29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", - "sha256:2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", - "sha256:3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", - "sha256:519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", - "sha256:57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa", - "sha256:668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", - "sha256:68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", - "sha256:6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", - "sha256:79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", - "sha256:8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", - "sha256:898f818399cafcdb93cbbe15fc83a33d05f18e29fb498ddc09b0214cdfc7cd51", - "sha256:94b091dc0f19291adcb279a108f5d38de2430411068b219f41b343c03b28fb1f", - "sha256:a26863198902cda15ab4503991e8cf1ca874219e0118cbf07c126bce7c4db129", - "sha256:a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", - "sha256:bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", - "sha256:c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", - "sha256:c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", - "sha256:edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", - "sha256:f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6" - ], - "markers": "python_version < '3.7' and implementation_name == 'cpython'", - "version": "==1.1.0" - }, - "urllib3": { - "hashes": [ - "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", - "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" - ], - "version": "==1.24.1" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "wheel": { - "hashes": [ - "sha256:196c9842d79262bb66fcf59faa4bd0deb27da911dbc7c6cdca931080eb1f0783", - "sha256:c93e2d711f5f9841e17f53b0e6c0ff85593f3b416b6eec7a9452041a59a42688" - ], - "index": "pypi", - "version": "==0.32.2" - }, - "wrapt": { - "hashes": [ - "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" - ], - "version": "==1.10.11" - } - } -} diff --git a/README.md b/README.md index ef76a1ff..eaca5e74 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ -Unix: [![Build Status](https://travis-ci.org/jacebrowning/gitman.svg?branch=develop)](https://travis-ci.org/jacebrowning/gitman) Windows: [![Windows Build Status](https://img.shields.io/appveyor/ci/jacebrowning/gitman/develop.svg)](https://ci.appveyor.com/project/jacebrowning/gitman)
Metrics: [![Coverage Status](https://img.shields.io/coveralls/jacebrowning/gitman/develop.svg)](https://coveralls.io/r/jacebrowning/gitman) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/jacebrowning/gitman.svg)](https://scrutinizer-ci.com/g/jacebrowning/gitman/?branch=develop)
Usage: [![PyPI Version](https://img.shields.io/pypi/v/GitMan.svg)](https://pypi.org/project/GitMan) - # Overview GitMan is a language-agnostic dependency manager using Git. It aims to serve as a submodules replacement and provides advanced options for managing versions of nested Git repositories. ![demo](https://raw.githubusercontent.com/jacebrowning/gitman/develop/docs/demo.gif) +[![Unix Build Status](https://img.shields.io/travis/jacebrowning/gitman/master.svg?label=unix)](https://travis-ci.org/jacebrowning/gitman) +[![Windows Build Status](https://img.shields.io/appveyor/ci/jacebrowning/gitman/master.svg?label=window)](https://ci.appveyor.com/project/jacebrowning/gitman) +[![Coverage Status](https://img.shields.io/coveralls/jacebrowning/gitman/master.svg)](https://coveralls.io/r/jacebrowning/gitman) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/jacebrowning/gitman.svg)](https://scrutinizer-ci.com/g/jacebrowning/gitman/?branch=master) +[![PyPI Version](https://img.shields.io/pypi/v/GitMan.svg)](https://pypi.org/project/GitMan) +[![PyPI License](https://img.shields.io/pypi/l/GitMan.svg)](https://pypi.org/project/GitMan) + # Setup ## Requirements diff --git a/bin/verchew b/bin/verchew index ee946972..8ff41f5d 100755 --- a/bin/verchew +++ b/bin/verchew @@ -32,6 +32,7 @@ from __future__ import unicode_literals import argparse import logging import os +import re import sys from collections import OrderedDict from subprocess import PIPE, STDOUT, Popen @@ -42,7 +43,7 @@ try: except ImportError: import ConfigParser as configparser # Python 2 -__version__ = '1.3' +__version__ = '1.5' PY2 = sys.version_info[0] == 2 CONFIG_FILENAMES = [ @@ -65,7 +66,7 @@ version = Python 2.7 [virtualenv] cli = virtualenv -version = 15. +version = 15 message = Only required with Python 2. [Make] @@ -218,8 +219,12 @@ def check_dependencies(config): def get_version(program, argument=None): - argument = argument or '--version' - args = [program, argument] + if argument is None: + args = [program, '--version'] + elif argument: + args = [program, argument] + else: + args = [program] show("$ {0}".format(" ".join(args))) output = call(args) @@ -229,7 +234,14 @@ def get_version(program, argument=None): def match_version(pattern, output): - return output.startswith(pattern) or " " + pattern in output + regex = pattern.replace('.', r'\.') + r'\b' + + log.debug("Matching %s: %s", regex, output) + match = re.match(regex, output) + if match is None: + match = re.match(r'.*[^\d.]' + regex, output) + + return bool(match) def call(args): diff --git a/gitman/__init__.py b/gitman/__init__.py index 769c4a5c..2d266a41 100644 --- a/gitman/__init__.py +++ b/gitman/__init__.py @@ -1,29 +1,15 @@ """Package for GitMan.""" -import sys +from pkg_resources import get_distribution +from .commands import ( # pylint: disable=redefined-builtin + delete as uninstall, + display as list, + init, + install, + lock, + update, +) -__project__ = 'GitMan' -__version__ = '1.6a3' -CLI = 'gitman' -PLUGIN = 'deps' -NAME = 'Git Dependency Manager' -VERSION = __project__ + ' v' + __version__ -DESCRIPTION = 'A language-agnostic dependency manager using Git.' - -PYTHON_VERSION = 3, 5 - -if sys.version_info < PYTHON_VERSION: # pragma: no cover (manual test) - sys.exit("Python {}.{}+ is required.".format(*PYTHON_VERSION)) - -try: - # pylint: disable=wrong-import-position - from .commands import init - from .commands import install - from .commands import update - from .commands import display as list # pylint: disable=redefined-builtin - from .commands import lock - from .commands import delete as uninstall -except ImportError: # pragma: no cover (manual test) - pass +__version__ = get_distribution('gitman').version diff --git a/gitman/__main__.py b/gitman/__main__.py index cb2b5e43..f5b17de5 100644 --- a/gitman/__main__.py +++ b/gitman/__main__.py @@ -1,17 +1,20 @@ """Package entry point.""" +import importlib +import os +import sys + +from gitman.cli import main + + # Declare itself as package if needed for better debugging support # pylint: disable=multiple-imports,wrong-import-position,redefined-builtin,used-before-assignment if __name__ == '__main__' and __package__ is None: # pragma: no cover - import os, sys, importlib parent_dir = os.path.abspath(os.path.dirname(__file__)) sys.path.append(os.path.dirname(parent_dir)) __package__ = os.path.basename(parent_dir) importlib.import_module(__package__) -from gitman.cli import main - - if __name__ == '__main__': # pragma: no cover main() diff --git a/gitman/cli.py b/gitman/cli.py index 03a509d6..63a5ace6 100644 --- a/gitman/cli.py +++ b/gitman/cli.py @@ -5,8 +5,9 @@ import argparse import logging import sys +from typing import Dict, List -from . import CLI, DESCRIPTION, VERSION, commands, common, exceptions +from . import __version__, commands, common, exceptions log = logging.getLogger(__name__) @@ -17,107 +18,196 @@ def main(args=None, function=None): # pylint: disable=too-many-statements # Shared options debug = argparse.ArgumentParser(add_help=False) - debug.add_argument('-V', '--version', action='version', version=VERSION) + debug.add_argument( + '-V', '--version', action='version', version="GitMan v" + __version__ + ) debug_group = debug.add_mutually_exclusive_group() - debug_group.add_argument('-v', '--verbose', action='count', default=0, - help="enable verbose logging") - debug_group.add_argument('-q', '--quiet', action='store_const', const=-1, - dest='verbose', - help="only display errors and prompts") + debug_group.add_argument( + '-v', '--verbose', action='count', default=0, help="enable verbose logging" + ) + debug_group.add_argument( + '-q', + '--quiet', + action='store_const', + const=-1, + dest='verbose', + help="only display errors and prompts", + ) project = argparse.ArgumentParser(add_help=False) - project.add_argument('-r', '--root', metavar='PATH', - help="root directory of the project") + project.add_argument( + '-r', '--root', metavar='PATH', help="root directory of the project" + ) depth = argparse.ArgumentParser(add_help=False) - depth.add_argument('-d', '--depth', type=common.positive_int, - default=5, metavar="NUM", - help="limit the number of dependency levels") + depth.add_argument( + '-d', + '--depth', + type=common.positive_int, + default=5, + metavar="NUM", + help="limit the number of dependency levels", + ) options = argparse.ArgumentParser(add_help=False) - options.add_argument('-c', '--clean', action='store_true', - help="delete ignored files in dependencies") + options.add_argument( + '-c', + '--clean', + action='store_true', + help="delete ignored files in dependencies", + ) options_group = options.add_mutually_exclusive_group() - options_group.add_argument('-f', '--force', action='store_true', - help=("overwrite uncommitted changes " - "in dependencies")) - options_group.add_argument('-s', '--skip-changes', action='store_true', - dest='skip_changes', - help=("skip dependencies with " - "uncommitted changes")) - - shared = {'formatter_class': common.WideHelpFormatter} + options_group.add_argument( + '-f', + '--force', + action='store_true', + help="overwrite uncommitted changes in dependencies", + ) + options_group.add_argument( + '-s', + '--skip-changes', + action='store_true', + dest='skip_changes', + help="skip dependencies with uncommitted changes", + ) # Main parser - parser = argparse.ArgumentParser(prog=CLI, description=DESCRIPTION, - parents=[debug], **shared) + parser = argparse.ArgumentParser( + prog='gitman', + description="A language-agnostic dependency manager using Git.", + parents=[debug], + formatter_class=common.WideHelpFormatter, + ) subs = parser.add_subparsers(help="", dest='command', metavar="") # Init parser info = "create a new config file for the project" - sub = subs.add_parser('init', description=info.capitalize() + '.', - help=info, parents=[debug], **shared) + sub = subs.add_parser( + 'init', + description=info.capitalize() + '.', + help=info, + parents=[debug], + formatter_class=common.WideHelpFormatter, + ) # Install parser info = "get the specified versions of all dependencies" - sub = subs.add_parser('install', description=info.capitalize() + '.', - help=info, parents=[debug, project, depth, options], - **shared) - sub.add_argument('name', nargs='*', - help="list of dependencies names to install") - sub.add_argument('-e', '--fetch', action='store_true', - help="always fetch the latest branches") + sub = subs.add_parser( + 'install', + description=info.capitalize() + '.', + help=info, + parents=[debug, project, depth, options], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument('name', nargs='*', help="list of dependencies names to install") + sub.add_argument( + '-e', '--fetch', action='store_true', help="always fetch the latest branches" + ) # Update parser info = "update dependencies to the latest versions" - sub = subs.add_parser('update', description=info.capitalize() + '.', - help=info, parents=[debug, project, depth, options], - **shared) - sub.add_argument('name', nargs='*', - help="list of dependencies names to update") - sub.add_argument('-a', '--all', action='store_true', dest='recurse', - help="also update all nested dependencies") - sub.add_argument('-L', '--skip-lock', - action='store_false', dest='lock', default=None, - help="disable recording of updated versions") + sub = subs.add_parser( + 'update', + description=info.capitalize() + '.', + help=info, + parents=[debug, project, depth, options], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument('name', nargs='*', help="list of dependencies names to update") + sub.add_argument( + '-a', + '--all', + action='store_true', + dest='recurse', + help="also update all nested dependencies", + ) + sub.add_argument( + '-L', + '--skip-lock', + action='store_false', + dest='lock', + default=None, + help="disable recording of updated versions", + ) # List parser info = "display the current version of each dependency" - sub = subs.add_parser('list', description=info.capitalize() + '.', - help=info, parents=[debug, project, depth], **shared) - sub.add_argument('-D', '--fail-if-dirty', action='store_false', - dest='allow_dirty', - help="fail if a source has uncommitted changes") + sub = subs.add_parser( + 'list', + description=info.capitalize() + '.', + help=info, + parents=[debug, project, depth], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument( + '-D', + '--fail-if-dirty', + action='store_false', + dest='allow_dirty', + help="fail if a source has uncommitted changes", + ) # Lock parser info = "lock the current version of each dependency" - sub = subs.add_parser('lock', description=info.capitalize() + '.', - help=info, parents=[debug, project], **shared) - sub.add_argument('name', nargs='*', - help="list of dependency names to lock") + sub = subs.add_parser( + 'lock', + description=info.capitalize() + '.', + help=info, + parents=[debug, project], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument('name', nargs='*', help="list of dependency names to lock") # Uninstall parser info = "delete all installed dependencies" - sub = subs.add_parser('uninstall', description=info.capitalize() + '.', - help=info, parents=[debug, project], **shared) - sub.add_argument('-f', '--force', action='store_true', - help="delete uncommitted changes in dependencies") - sub.add_argument('-k', '--keep-location', dest='keep_location', - default=False, action='store_true', - help="keep top level folder location") + sub = subs.add_parser( + 'uninstall', + description=info.capitalize() + '.', + help=info, + parents=[debug, project], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument( + '-f', + '--force', + action='store_true', + help="delete uncommitted changes in dependencies", + ) + sub.add_argument( + '-k', + '--keep-location', + dest='keep_location', + default=False, + action='store_true', + help="keep top level folder location", + ) # Show parser info = "display the path of a dependency or internal file" - sub = subs.add_parser('show', description=info.capitalize() + '.', - help=info, parents=[debug, project], **shared) - sub.add_argument('name', nargs='*', - help="display the path of this dependency") - sub.add_argument('-c', '--config', action='store_true', - help="display the path of the config file") - sub.add_argument('-l', '--log', action='store_true', - help="display the path of the log file") + sub = subs.add_parser( + 'show', + description=info.capitalize() + '.', + help=info, + parents=[debug, project], + formatter_class=common.WideHelpFormatter, + ) + sub.add_argument('name', nargs='*', help="display the path of this dependency") + sub.add_argument( + '-c', + '--config', + action='store_true', + help="display the path of the config file", + ) + sub.add_argument( + '-l', '--log', action='store_true', help="display the path of the log file" + ) # Edit parser info = "open the config file in the default editor" - sub = subs.add_parser('edit', description=info.capitalize() + '.', - help=info, parents=[debug, project], **shared) + sub = subs.add_parser( + 'edit', + description=info.capitalize() + '.', + help=info, + parents=[debug, project], + formatter_class=common.WideHelpFormatter, + ) # Parse arguments namespace = parser.parse_args(args=args) @@ -135,8 +225,8 @@ def main(args=None, function=None): # pylint: disable=too-many-statements def _get_command(function, namespace): # pylint: disable=too-many-statements - args = [] - kwargs = {} + args: List = [] + kwargs: Dict = {} if namespace.command == 'init': function = commands.init @@ -144,22 +234,25 @@ def _get_command(function, namespace): # pylint: disable=too-many-statements elif namespace.command in ['install', 'update']: function = getattr(commands, namespace.command) args = namespace.name - kwargs.update(root=namespace.root, - depth=namespace.depth, - force=namespace.force, - clean=namespace.clean, - skip_changes=namespace.skip_changes) + kwargs.update( + root=namespace.root, + depth=namespace.depth, + force=namespace.force, + clean=namespace.clean, + skip_changes=namespace.skip_changes, + ) if namespace.command == 'install': kwargs.update(fetch=namespace.fetch) if namespace.command == 'update': - kwargs.update(recurse=namespace.recurse, - lock=namespace.lock) + kwargs.update(recurse=namespace.recurse, lock=namespace.lock) elif namespace.command == 'list': function = commands.display - kwargs.update(root=namespace.root, - depth=namespace.depth, - allow_dirty=namespace.allow_dirty) + kwargs.update( + root=namespace.root, + depth=namespace.depth, + allow_dirty=namespace.allow_dirty, + ) elif namespace.command == 'lock': function = getattr(commands, namespace.command) @@ -168,9 +261,11 @@ def _get_command(function, namespace): # pylint: disable=too-many-statements elif namespace.command == 'uninstall': function = commands.delete - kwargs.update(root=namespace.root, - force=namespace.force, - keep_location=namespace.keep_location) + kwargs.update( + root=namespace.root, + force=namespace.force, + keep_location=namespace.keep_location, + ) elif namespace.command == 'show': function = commands.show @@ -198,8 +293,10 @@ def _run_command(function, args, kwargs): log.debug("Command canceled") except exceptions.UncommittedChanges as exception: _show_error(exception) - exit_message = ("Run again with '--force' to discard changes " - "or '--skip-changes' to skip this dependency") + exit_message = ( + "Run again with '--force' to discard changes " + "or '--skip-changes' to skip this dependency" + ) except exceptions.ScriptFailure as exception: _show_error(exception) exit_message = "Run again with '--force' to ignore script errors" diff --git a/gitman/commands.py b/gitman/commands.py index f82c7d71..d50cad2f 100644 --- a/gitman/commands.py +++ b/gitman/commands.py @@ -19,6 +19,7 @@ def wrapped(*args, **kwargs): result = func(*args, **kwargs) os.chdir(cwd) return result + return wrapped @@ -34,9 +35,11 @@ def init(): else: config = Config() - source = Source('git', - name="sample_dependency", - repo="https://github.com/githubtraining/hellogitworld") + source = Source( + 'git', + name="sample_dependency", + repo="https://github.com/githubtraining/hellogitworld", + ) config.sources.append(source) source = source.lock(rev="ebbbf773431ba07510251bb03f9525c7bab2b13a") config.sources_locked.append(source) @@ -53,8 +56,15 @@ def init(): @restore_cwd -def install(*names, root=None, depth=None, - force=False, fetch=False, clean=True, skip_changes=False): +def install( + *names, + root=None, + depth=None, + force=False, + fetch=False, + clean=True, + skip_changes=False, +): """Install dependencies for a project. Optional arguments: @@ -69,9 +79,11 @@ def install(*names, root=None, depth=None, - `skip_changes`: indicates dependencies with uncommitted changes should be skipped """ - log.info("%sInstalling dependencies: %s", - 'force-' if force else '', - ', '.join(names) if names else '') + log.info( + "%sInstalling dependencies: %s", + 'force-' if force else '', + ', '.join(names) if names else '', + ) count = None config = load_config(root) @@ -81,8 +93,13 @@ def install(*names, root=None, depth=None, common.show("Installing dependencies...", color='message', log=False) common.newline() count = config.install_dependencies( - *names, update=False, depth=depth, - force=force, fetch=fetch, clean=clean, skip_changes=skip_changes + *names, + update=False, + depth=depth, + force=force, + fetch=fetch, + clean=clean, + skip_changes=skip_changes, ) if count: @@ -92,9 +109,16 @@ def install(*names, root=None, depth=None, @restore_cwd -def update(*names, root=None, depth=None, - recurse=False, force=False, clean=True, lock=None, # pylint: disable=redefined-outer-name - skip_changes=False): +def update( + *names, + root=None, + depth=None, + recurse=False, + force=False, + clean=True, + lock=None, # pylint: disable=redefined-outer-name + skip_changes=False, +): """Update dependencies for a project. Optional arguments: @@ -110,10 +134,12 @@ def update(*names, root=None, depth=None, - `skip_changes`: indicates dependencies with uncommitted changes should be skipped """ - log.info("%s dependencies%s: %s", - 'Force updating' if force else 'Updating', - ', recursively' if recurse else '', - ', '.join(names) if names else '') + log.info( + "%s dependencies%s: %s", + 'Force updating' if force else 'Updating', + ', recursively' if recurse else '', + ', '.join(names) if names else '', + ) count = None config = load_config(root) @@ -123,17 +149,22 @@ def update(*names, root=None, depth=None, common.show("Updating dependencies...", color='message', log=False) common.newline() count = config.install_dependencies( - *names, update=True, depth=depth, - recurse=recurse, force=force, fetch=True, clean=clean, - skip_changes=skip_changes + *names, + update=True, + depth=depth, + recurse=recurse, + force=force, + fetch=True, + clean=clean, + skip_changes=skip_changes, ) if count and lock is not False: - common.show("Recording installed versions...", - color='message', log=False) + common.show("Recording installed versions...", color='message', log=False) common.newline() - config.lock_dependencies(*names, obey_existing=lock is None, - skip_changes=skip_changes) + config.lock_dependencies( + *names, obey_existing=lock is None, skip_changes=skip_changes + ) if count: _run_scripts(*names, depth=depth, force=force, _config=config) @@ -176,13 +207,13 @@ def display(*, root=None, depth=None, allow_dirty=True): if config: common.newline() - common.show("Displaying current dependency versions...", - color='message', log=False) + common.show( + "Displaying current dependency versions...", color='message', log=False + ) common.newline() config.log(datetime.datetime.now().strftime("%F %T")) count = 0 - for identity in config.get_dependencies(depth=depth, - allow_dirty=allow_dirty): + for identity in config.get_dependencies(depth=depth, allow_dirty=allow_dirty): count += 1 config.log("{}: {} @ {}", *identity) config.log() @@ -233,8 +264,7 @@ def delete(*, root=None, force=False, keep_location=False): if config: common.newline() - common.show("Checking for uncommitted changes...", - color='message', log=False) + common.show("Checking for uncommitted changes...", color='message', log=False) common.newline() count = len(list(config.get_dependencies(allow_dirty=force))) common.dedent(level=0) diff --git a/gitman/common.py b/gitman/common.py index b84eb43e..e7554d5a 100644 --- a/gitman/common.py +++ b/gitman/common.py @@ -15,7 +15,8 @@ class WideHelpFormatter(argparse.HelpFormatter): """Command-line help text formatter with wider help text.""" def __init__(self, *args, **kwargs): - super().__init__(*args, max_help_position=40, **kwargs) + kwargs['max_help_position'] = 40 + super().__init__(*args, **kwargs) class WarningFormatter(logging.Formatter): @@ -81,8 +82,9 @@ def configure_logging(count=0): # Set a custom formatter logging.basicConfig(level=level) logging.captureWarnings(True) - formatter = WarningFormatter(default_format, verbose_format, - datefmt=settings.LOGGING_DATEFMT) + formatter = WarningFormatter( + default_format, verbose_format, datefmt=settings.LOGGING_DATEFMT + ) logging.root.handlers[0].setFormatter(formatter) logging.getLogger('yorm').setLevel(max(level, settings.YORM_LOGGING_LEVEL)) @@ -165,14 +167,13 @@ def style(msg, name=None, *, _color_support=False): return msg if name == 'shell': - return msg.replace("$ ", COLORS.get(name) + "$ " + RESET) + return msg.replace("$ ", COLORS[name] + "$ " + RESET) color = COLORS.get(name) if color: return color + msg + RESET if msg: - assert color is not None, \ - "Unknown style name requested: {!r}".format(name) + assert color is not None, "Unknown style name requested: {!r}".format(name) return msg diff --git a/gitman/git.py b/gitman/git.py index 76792dad..01f7395f 100644 --- a/gitman/git.py +++ b/gitman/git.py @@ -22,8 +22,7 @@ def gitsvn(*args, **kwargs): return call('git', 'svn', *args, **kwargs) -def clone(type, repo, path, *, - cache=settings.CACHE, sparse_paths=None, rev=None): +def clone(type, repo, path, *, cache=settings.CACHE, sparse_paths=None, rev=None): """Clone a new Git repository.""" log.debug("Creating a new repository...") @@ -52,11 +51,13 @@ def clone(type, repo, path, *, git('-C', normpath, 'config', 'core.sparseCheckout', 'true') git('-C', normpath, 'remote', 'add', '-f', 'origin', sparse_paths_repo) - with open("%s/%s/.git/info/sparse-checkout" % - (os.getcwd(), normpath), 'w') as fd: + with open( + "%s/%s/.git/info/sparse-checkout" % (os.getcwd(), normpath), 'w' + ) as fd: fd.writelines(sparse_paths) - with open("%s/%s/.git/objects/info/alternates" % - (os.getcwd(), normpath), 'w') as fd: + with open( + "%s/%s/.git/objects/info/alternates" % (os.getcwd(), normpath), 'w' + ) as fd: fd.write("%s/objects" % sparse_paths_repo) # We use directly the revision requested here in order to respect, @@ -145,7 +146,9 @@ def changes(type, include_untracked=False, display_status=True, _show=False): return status -def update(type, repo, path, *, clean=True, fetch=False, rev=None): # pylint: disable=redefined-outer-name,unused-argument +def update( + type, repo, path, *, clean=True, fetch=False, rev=None +): # pylint: disable=redefined-outer-name,unused-argument if type == 'git-svn': # make deep clone here for simplification of sources.py @@ -202,8 +205,7 @@ def get_hash(type, _show=False): def get_tag(): """Get the current working tree's tag (if on a tag).""" - return git('describe', '--tags', '--exact-match', - _show=False, _ignore=True)[0] + return git('describe', '--tags', '--exact-match', _show=False, _ignore=True)[0] def is_fetch_required(type, rev): @@ -212,9 +214,7 @@ def is_fetch_required(type, rev): assert type == 'git' - return rev not in (get_branch(), - get_hash(type), - get_tag()) + return rev not in (get_branch(), get_hash(type), get_tag()) def get_branch(): @@ -229,6 +229,7 @@ def _get_sha_from_rev(rev): branch = parts[0] date = parts[1].strip("{}") git('checkout', '--force', branch, _show=False) - rev = git('rev-list', '-n', '1', '--before={!r}'.format(date), - branch, _show=False)[0] + rev = git( + 'rev-list', '-n', '1', '--before={!r}'.format(date), branch, _show=False + )[0] return rev diff --git a/gitman/models/config.py b/gitman/models/config.py index 4c2d1879..93b384f6 100644 --- a/gitman/models/config.py +++ b/gitman/models/config.py @@ -1,11 +1,12 @@ import logging import os +from typing import List import yorm from yorm.types import SortedList, String -from . import Source from .. import common, shell +from .source import Source log = logging.getLogger(__name__) @@ -20,14 +21,13 @@ class Config(yorm.ModelMixin): LOG = "gitman.log" - def __init__(self, root=None, - filename="gitman.yml", location="gitman_sources"): + def __init__(self, root=None, filename="gitman.yml", location="gitman_sources"): super().__init__() self.root = root or os.getcwd() self.filename = filename self.location = location - self.sources = [] - self.sources_locked = [] + self.sources: List[Source] = [] + self.sources_locked: List[Source] = [] def _on_post_load(self): for source in self.sources: @@ -39,6 +39,7 @@ def _on_post_load(self): def config_path(self): """Get the full path to the config file.""" return os.path.normpath(os.path.join(self.root, self.filename)) + path = config_path @property @@ -62,10 +63,17 @@ def get_path(self, name=None): return os.path.normpath(os.path.join(base, name)) return base - def install_dependencies(self, *names, depth=None, - update=True, recurse=False, - force=False, fetch=False, clean=True, - skip_changes=False): + def install_dependencies( + self, + *names, + depth=None, + update=True, + recurse=False, + force=False, + fetch=False, + clean=True, + skip_changes=False, + ): """Download or update the specified dependencies.""" if depth == 0: log.info("Skipped directory: %s", self.location_path) @@ -88,8 +96,9 @@ def install_dependencies(self, *names, depth=None, log.info("Skipped dependency: %s", source.name) continue - source.update_files(force=force, fetch=fetch, clean=clean, - skip_changes=skip_changes) + source.update_files( + force=force, fetch=fetch, clean=clean, skip_changes=skip_changes + ) source.create_link(self.root, force=force) common.newline() count += 1 @@ -104,7 +113,7 @@ def install_dependencies(self, *names, depth=None, force=force, fetch=fetch, clean=clean, - skip_changes=skip_changes + skip_changes=skip_changes, ) common.dedent() @@ -140,8 +149,7 @@ def run_scripts(self, *names, depth=None, force=False): if config: common.indent() count += config.run_scripts( - depth=None if depth is None else max(0, depth - 1), - force=force, + depth=None if depth is None else max(0, depth - 1), force=force ) common.dedent() @@ -151,8 +159,7 @@ def run_scripts(self, *names, depth=None, force=False): return count - def lock_dependencies(self, *names, obey_existing=True, - skip_changes=False): + def lock_dependencies(self, *names, obey_existing=True, skip_changes=False): """Lock down the immediate dependency versions.""" sources = self._get_sources(use_locked=obey_existing).copy() sources_filter = list(names) if names else [s.name for s in sources] @@ -264,7 +271,7 @@ def _get_sources(self, *, use_locked=None): log.info("No locked sources, defaulting to none...") return [] - sources = [] + sources: List[Source] = [] if use_locked is False: sources = self.sources else: @@ -278,8 +285,7 @@ def _get_sources(self, *, use_locked=None): extras = [] for source in self.sources + self.sources_locked: if source not in sources: - log.info("Source %r missing from selected section", - source.name) + log.info("Source %r missing from selected section", source.name) extras.append(source) return sources + extras diff --git a/gitman/models/source.py b/gitman/models/source.py index 03a22e3c..cd42e0d7 100644 --- a/gitman/models/source.py +++ b/gitman/models/source.py @@ -24,8 +24,16 @@ class Source(AttributeDictionary): DIRTY = '' UNKNOWN = '' - def __init__(self, type, repo, name=None, rev='master', - link=None, scripts=None, sparse_paths=None): + def __init__( + self, + type, + repo, + name=None, + rev='master', + link=None, + scripts=None, + sparse_paths=None, + ): super().__init__() self.type = type or 'git' @@ -51,8 +59,9 @@ def __str__(self): pattern = "['{t}'] '{r}' @ '{v}' in '{d}'" if self.link: pattern += " <- '{s}'" - return pattern.format(t=self.type, r=self.repo, - v=self.rev, d=self.name, s=self.link) + return pattern.format( + t=self.type, r=self.repo, v=self.rev, d=self.name, s=self.link + ) def __eq__(self, other): return self.name == other.name @@ -63,15 +72,19 @@ def __ne__(self, other): def __lt__(self, other): return self.name < other.name - def update_files(self, force=False, fetch=False, clean=True, - skip_changes=False): + def update_files(self, force=False, fetch=False, clean=True, skip_changes=False): """Ensure the source matches the specified revision.""" log.info("Updating source files...") # Clone the repository if needed if not os.path.exists(self.name): - git.clone(self.type, self.repo, self.name, - sparse_paths=self.sparse_paths, rev=self.rev) + git.clone( + self.type, + self.repo, + self.name, + sparse_paths=self.sparse_paths, + rev=self.rev, + ) # Enter the working tree shell.cd(self.name) @@ -82,24 +95,28 @@ def update_files(self, force=False, fetch=False, clean=True, if not force: log.debug("Confirming there are no uncommitted changes...") if skip_changes: - if git.changes(self.type, include_untracked=clean, - display_status=False): - msg = ("Skipped update due to uncommitted changes " - "in {}").format(os.getcwd()) - common.show(msg, color='git_changes') + if git.changes( + self.type, include_untracked=clean, display_status=False + ): + common.show( + f'Skipped update due to uncommitted changes in {os.getcwd()}', + color='git_changes', + ) return else: if git.changes(self.type, include_untracked=clean): - msg = "Uncommitted changes in {}".format(os.getcwd()) - raise exceptions.UncommittedChanges(msg) + raise exceptions.UncommittedChanges( + f'Uncommitted changes in {os.getcwd()}' + ) # Fetch the desired revision if fetch or git.is_fetch_required(self.type, self.rev): git.fetch(self.type, self.repo, self.name, rev=self.rev) # Update the working tree to the desired revision - git.update(self.type, self.repo, self.name, - fetch=fetch, clean=clean, rev=self.rev) + git.update( + self.type, self.repo, self.name, fetch=fetch, clean=clean, rev=self.rev + ) def create_link(self, root, force=False): """Create a link from the target name to the current directory.""" @@ -156,8 +173,7 @@ def run_scripts(self, force=False): common.show(*lines, color='shell_output') common.newline() - def identify(self, allow_dirty=True, allow_missing=True, - skip_changes=False): + def identify(self, allow_dirty=True, allow_missing=True, skip_changes=False): """Get the path and current repository URL and hash.""" if os.path.isdir(self.name): @@ -167,9 +183,11 @@ def identify(self, allow_dirty=True, allow_missing=True, path = os.getcwd() url = git.get_url(self.type) - if git.changes(self.type, - display_status=not allow_dirty and not skip_changes, - _show=not skip_changes): + if git.changes( + self.type, + display_status=not allow_dirty and not skip_changes, + _show=not skip_changes, + ): if allow_dirty: common.show(self.DIRTY, color='git_dirty', log=False) @@ -177,8 +195,9 @@ def identify(self, allow_dirty=True, allow_missing=True, return path, url, self.DIRTY if skip_changes: - msg = ("Skipped lock due to uncommitted changes " - "in {}").format(os.getcwd()) + msg = ("Skipped lock due to uncommitted changes " "in {}").format( + os.getcwd() + ) common.show(msg, color='git_changes') common.newline() return path, url, self.DIRTY @@ -204,17 +223,22 @@ def lock(self, rev=None, allow_dirty=False, skip_changes=False): """ if rev is None: - _, _, rev = self.identify(allow_dirty=allow_dirty, - allow_missing=False, - skip_changes=skip_changes) + _, _, rev = self.identify( + allow_dirty=allow_dirty, allow_missing=False, skip_changes=skip_changes + ) if rev == self.DIRTY: return None - source = self.__class__(self.type, self.repo, - self.name, rev, - self.link, self.scripts, - self.sparse_paths) + source = self.__class__( + self.type, + self.repo, + self.name, + rev, + self.link, + self.scripts, + self.sparse_paths, + ) return source @property diff --git a/gitman/plugin.py b/gitman/plugin.py index 41d3a97e..bfa3c10c 100644 --- a/gitman/plugin.py +++ b/gitman/plugin.py @@ -5,12 +5,12 @@ import argparse import logging -from . import NAME, PLUGIN, __version__, common +from . import __version__, common from .cli import _get_command, _run_command -PROG = 'git ' + PLUGIN -DESCRIPTION = "Use {} (v{}) to install repostories.".format(NAME, __version__) +PROG = 'git deps' +DESCRIPTION = "Use GitMan (v{}) to install repositories.".format(__version__) log = logging.getLogger(__name__) @@ -21,47 +21,80 @@ def main(args=None): # Main parser parser = argparse.ArgumentParser(prog=PROG, description=DESCRIPTION) parser.add_argument( - '-f', '--force', action='store_true', + '-f', + '--force', + action='store_true', help="overwrite uncommitted changes in dependencies", ) parser.add_argument( - '-s', '--skip-changes', action='store_true', dest='skip_changes', - help="skip dependencies with uncommitted changes" + '-s', + '--skip-changes', + action='store_true', + dest='skip_changes', + help="skip dependencies with uncommitted changes", ) parser.add_argument( - '-c', '--clean', action='store_true', + '-c', + '--clean', + action='store_true', help="delete ignored files when updating dependencies", ) # Options group group = parser.add_mutually_exclusive_group() - shared = dict(action='store_const', dest='command') # Update option group.add_argument( - '-u', '--update', const='update', - help="update dependencies to the latest versions", **shared + '-u', + '--update', + const='update', + help="update dependencies to the latest versions", + action='store_const', + dest='command', + ) + parser.add_argument( + '-a', + '--all', + action='store_true', + dest='recurse', + help="include nested dependencies when updating", + ) + parser.add_argument( + '-L', + '--skip-lock', + action='store_false', + dest='lock', + default=True, + help="disable recording of updated versions", ) - parser.add_argument('-a', '--all', action='store_true', dest='recurse', - help="include nested dependencies when updating") - parser.add_argument('-L', '--skip-lock', - action='store_false', dest='lock', default=True, - help="disable recording of updated versions") # Display option group.add_argument( - '-l', '--list', const='list', - help="display the current version of each dependency", **shared + '-l', + '--list', + const='list', + help="display the current version of each dependency", + action='store_const', + dest='command', ) # Uninstall option group.add_argument( - '-x', '--uninstall', const='uninstall', - help="delete all installed dependencies", **shared + '-x', + '--uninstall', + const='uninstall', + help="delete all installed dependencies", + action='store_const', + dest='command', + ) + parser.add_argument( + '-k', + '--keep-location', + action='store_true', + dest='keep_location', + default=False, + help='keep top level folder location', ) - parser.add_argument('-k', '--keep-location', action='store_true', - dest='keep_location', default=False, - help='keep top level folder location') # Parse arguments namespace = parser.parse_args(args=args) diff --git a/gitman/settings.py b/gitman/settings.py index 52f58a6f..7b302377 100644 --- a/gitman/settings.py +++ b/gitman/settings.py @@ -12,7 +12,7 @@ DEFAULT_LOGGING_FORMAT = "%(message)s" LEVELED_LOGGING_FORMAT = "%(levelname)s: %(message)s" VERBOSE_LOGGING_FORMAT = "[%(levelname)-8s] %(message)s" -VERBOSE2_LOGGING_FORMAT = "[%(levelname)-8s] (%(name)s @%(lineno)4d) %(message)s" # pylint: disable=C0301 +VERBOSE2_LOGGING_FORMAT = "[%(levelname)-8s] (%(name)s @%(lineno)4d) %(message)s" QUIET_LOGGING_LEVEL = logging.ERROR DEFAULT_LOGGING_LEVEL = logging.WARNING VERBOSE_LOGGING_LEVEL = logging.INFO diff --git a/gitman/shell.py b/gitman/shell.py index 6a1cce18..12c2ade5 100644 --- a/gitman/shell.py +++ b/gitman/shell.py @@ -28,9 +28,11 @@ def call(name, *args, _show=True, _shell=False, _ignore=False): program = show(name, *args, stdout=_show) command = subprocess.run( - name if _shell else [name, *args], universal_newlines=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - shell=_shell + name if _shell else [name, *args], + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=_shell, ) output = [line.strip() for line in command.stdout.splitlines()] @@ -47,9 +49,12 @@ def call(name, *args, _show=True, _shell=False, _ignore=False): message = ( "An external program call failed." + "\n\n" "In working directory: " + os.getcwd() + "\n\n" - "The following command produced a non-zero return code:" + "\n\n" + - CMD_PREFIX + program + "\n" + - command.stdout.strip() + "The following command produced a non-zero return code:" + + "\n\n" + + CMD_PREFIX + + program + + "\n" + + command.stdout.strip() ) raise ShellError(message, program=program, output=output) diff --git a/gitman/system.py b/gitman/system.py index a22599bb..8eadc419 100644 --- a/gitman/system.py +++ b/gitman/system.py @@ -26,7 +26,8 @@ def launch(path): def _launch_windows(path): # pragma: no cover (manual test) - os.startfile(path) # pylint: disable=no-member + # pylint: disable=no-member + os.startfile(path) # type: ignore return True diff --git a/gitman/tests/conftest.py b/gitman/tests/conftest.py index 9d32d556..eae41e30 100644 --- a/gitman/tests/conftest.py +++ b/gitman/tests/conftest.py @@ -24,8 +24,7 @@ def pytest_configure(config): terminal = config.pluginmanager.getplugin('terminal') - class QuietReporter(terminal.TerminalReporter): - + class QuietReporter(terminal.TerminalReporter): # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.verbosity = 0 diff --git a/gitman/tests/test_cli.py b/gitman/tests/test_cli.py index d202beaa..2edb3130 100644 --- a/gitman/tests/test_cli.py +++ b/gitman/tests/test_cli.py @@ -70,8 +70,13 @@ def test_install(self, mock_install): cli.main(['install']) mock_install.assert_called_once_with( - root=None, depth=5, force=False, fetch=False, clean=False, - skip_changes=False) + root=None, + depth=5, + force=False, + fetch=False, + clean=False, + skip_changes=False, + ) @patch('gitman.commands.install') def test_install_root(self, mock_install): @@ -79,9 +84,13 @@ def test_install_root(self, mock_install): cli.main(['install', '--root', 'mock/path/to/root']) mock_install.assert_called_once_with( - root='mock/path/to/root', depth=5, - force=False, fetch=False, clean=False, - skip_changes=False) + root='mock/path/to/root', + depth=5, + force=False, + fetch=False, + clean=False, + skip_changes=False, + ) @patch('gitman.commands.install') def test_install_force(self, mock_install): @@ -89,8 +98,8 @@ def test_install_force(self, mock_install): cli.main(['install', '--force']) mock_install.assert_called_once_with( - root=None, depth=5, force=True, fetch=False, clean=False, - skip_changes=False) + root=None, depth=5, force=True, fetch=False, clean=False, skip_changes=False + ) @patch('gitman.commands.install') def test_install_fetch(self, mock_install): @@ -98,8 +107,8 @@ def test_install_fetch(self, mock_install): cli.main(['install', '--fetch']) mock_install.assert_called_once_with( - root=None, depth=5, force=False, fetch=True, clean=False, - skip_changes=False) + root=None, depth=5, force=False, fetch=True, clean=False, skip_changes=False + ) @patch('gitman.commands.install') def test_install_clean(self, mock_install): @@ -107,8 +116,8 @@ def test_install_clean(self, mock_install): cli.main(['install', '--clean']) mock_install.assert_called_once_with( - root=None, depth=5, force=False, fetch=False, clean=True, - skip_changes=False) + root=None, depth=5, force=False, fetch=False, clean=True, skip_changes=False + ) @patch('gitman.commands.install') def test_install_specific_sources(self, mock_install): @@ -116,9 +125,15 @@ def test_install_specific_sources(self, mock_install): cli.main(['install', 'foo', 'bar']) mock_install.assert_called_once_with( - 'foo', 'bar', root=None, depth=5, - force=False, fetch=False, clean=False, - skip_changes=False) + 'foo', + 'bar', + root=None, + depth=5, + force=False, + fetch=False, + clean=False, + skip_changes=False, + ) @patch('gitman.commands.install') def test_install_with_depth(self, mock_update): @@ -126,8 +141,13 @@ def test_install_with_depth(self, mock_update): cli.main(['install', '--depth', '10']) mock_update.assert_called_once_with( - root=None, depth=10, force=False, fetch=False, clean=False, - skip_changes=False) + root=None, + depth=10, + force=False, + fetch=False, + clean=False, + skip_changes=False, + ) @patch('gitman.commands.install', Mock()) def test_install_with_depth_invalid(self): @@ -147,9 +167,14 @@ def test_update(self, mock_update): cli.main(['update']) mock_update.assert_called_once_with( - root=None, depth=5, - force=False, clean=False, recurse=False, lock=None, - skip_changes=False) + root=None, + depth=5, + force=False, + clean=False, + recurse=False, + lock=None, + skip_changes=False, + ) @patch('gitman.commands.update') def test_update_recursive(self, mock_update): @@ -157,9 +182,14 @@ def test_update_recursive(self, mock_update): cli.main(['update', '--all']) mock_update.assert_called_once_with( - root=None, depth=5, - force=False, clean=False, recurse=True, lock=None, - skip_changes=False) + root=None, + depth=5, + force=False, + clean=False, + recurse=True, + lock=None, + skip_changes=False, + ) @patch('gitman.commands.update') def test_update_no_lock(self, mock_update): @@ -167,9 +197,14 @@ def test_update_no_lock(self, mock_update): cli.main(['update', '--skip-lock']) mock_update.assert_called_once_with( - root=None, depth=5, - force=False, clean=False, recurse=False, lock=False, - skip_changes=False) + root=None, + depth=5, + force=False, + clean=False, + recurse=False, + lock=False, + skip_changes=False, + ) @patch('gitman.commands.update') def test_update_skip_changes(self, mock_update): @@ -177,9 +212,14 @@ def test_update_skip_changes(self, mock_update): cli.main(['update', '--skip-changes']) mock_update.assert_called_once_with( - root=None, depth=5, - force=False, clean=False, recurse=False, lock=None, - skip_changes=True) + root=None, + depth=5, + force=False, + clean=False, + recurse=False, + lock=None, + skip_changes=True, + ) @patch('gitman.commands.update') def test_update_specific_sources(self, mock_install): @@ -187,9 +227,16 @@ def test_update_specific_sources(self, mock_install): cli.main(['update', 'foo', 'bar']) mock_install.assert_called_once_with( - 'foo', 'bar', root=None, depth=5, - force=False, clean=False, recurse=False, lock=None, - skip_changes=False) + 'foo', + 'bar', + root=None, + depth=5, + force=False, + clean=False, + recurse=False, + lock=None, + skip_changes=False, + ) @patch('gitman.commands.update') def test_update_with_depth(self, mock_update): @@ -197,9 +244,14 @@ def test_update_with_depth(self, mock_update): cli.main(['update', '--depth', '10']) mock_update.assert_called_once_with( - root=None, depth=10, - force=False, clean=False, recurse=False, lock=None, - skip_changes=False) + root=None, + depth=10, + force=False, + clean=False, + recurse=False, + lock=None, + skip_changes=False, + ) class TestList: @@ -210,8 +262,7 @@ def test_list(self, mock_display): """Verify the 'list' command can be run.""" cli.main(['list']) - mock_display.assert_called_once_with( - root=None, depth=5, allow_dirty=True) + mock_display.assert_called_once_with(root=None, depth=5, allow_dirty=True) @patch('gitman.commands.display') def test_list_root(self, mock_display): @@ -219,27 +270,25 @@ def test_list_root(self, mock_display): cli.main(['list', '--root', 'mock/path/to/root']) mock_display.assert_called_once_with( - root='mock/path/to/root', depth=5, allow_dirty=True) + root='mock/path/to/root', depth=5, allow_dirty=True + ) @patch('gitman.commands.display') def test_list_no_dirty(self, mock_display): """Verify the 'list' command can be set to fail when dirty.""" cli.main(['list', '--fail-if-dirty']) - mock_display.assert_called_once_with( - root=None, depth=5, allow_dirty=False) + mock_display.assert_called_once_with(root=None, depth=5, allow_dirty=False) @patch('gitman.commands.display') def test_update_with_depth(self, mock_update): """Verify the 'list' command can be limited by depth.""" cli.main(['list', '--depth', '10']) - mock_update.assert_called_once_with( - root=None, depth=10, allow_dirty=True) + mock_update.assert_called_once_with(root=None, depth=10, allow_dirty=True) def describe_lock(): - @patch('gitman.commands.lock') def with_no_arguments(lock): cli.main(['lock']) @@ -260,7 +309,8 @@ def test_uninstall(self, mock_uninstall): cli.main(['uninstall']) mock_uninstall.assert_called_once_with( - root=None, force=False, keep_location=False) + root=None, force=False, keep_location=False + ) @patch('gitman.commands.delete') def test_uninstall_root(self, mock_uninstall): @@ -268,7 +318,8 @@ def test_uninstall_root(self, mock_uninstall): cli.main(['uninstall', '--root', 'mock/path/to/root']) mock_uninstall.assert_called_once_with( - root='mock/path/to/root', force=False, keep_location=False) + root='mock/path/to/root', force=False, keep_location=False + ) @patch('gitman.commands.delete') def test_uninstall_force(self, mock_uninstall): @@ -276,7 +327,8 @@ def test_uninstall_force(self, mock_uninstall): cli.main(['uninstall', '--force']) mock_uninstall.assert_called_once_with( - root=None, force=True, keep_location=False) + root=None, force=True, keep_location=False + ) @patch('gitman.commands.delete') def test_uninstall_keep_location(self, mock_uninstall): @@ -284,11 +336,11 @@ def test_uninstall_keep_location(self, mock_uninstall): cli.main(['uninstall', '--keep-location']) mock_uninstall.assert_called_once_with( - root=None, force=False, keep_location=True) + root=None, force=False, keep_location=True + ) def describe_show(): - @patch('gitman.commands.show') def with_no_arguments(show): cli.main(['show']) @@ -316,7 +368,6 @@ def with_log(show): def describe_edit(): - @patch('gitman.commands.edit') def with_no_arguments(edit): cli.main(['edit']) @@ -342,7 +393,6 @@ def describe_logging(): @pytest.mark.parametrize("argument,verbosity", argument_verbosity) def at_each_level(argument, verbosity): - def function(*args, **kwargs): logging.debug(args) logging.debug(kwargs) diff --git a/gitman/tests/test_commands.py b/gitman/tests/test_commands.py index ef9b078a..b98cf809 100644 --- a/gitman/tests/test_commands.py +++ b/gitman/tests/test_commands.py @@ -6,7 +6,6 @@ def describe_install(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -14,7 +13,6 @@ def can_be_run_without_project(tmpdir): def describe_update(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -22,7 +20,6 @@ def can_be_run_without_project(tmpdir): def describe_display(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -30,7 +27,6 @@ def can_be_run_without_project(tmpdir): def describe_lock(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -38,7 +34,6 @@ def can_be_run_without_project(tmpdir): def describe_delete(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -46,7 +41,6 @@ def can_be_run_without_project(tmpdir): def describe_show(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() @@ -54,7 +48,6 @@ def can_be_run_without_project(tmpdir): def describe_edit(): - def can_be_run_without_project(tmpdir): tmpdir.chdir() diff --git a/gitman/tests/test_common.py b/gitman/tests/test_common.py index 324c51d2..b0f11bbc 100644 --- a/gitman/tests/test_common.py +++ b/gitman/tests/test_common.py @@ -10,7 +10,6 @@ class TestShowConsole: - def setup_method(self, _): _Config.indent_level = 0 _Config.verbosity = 0 @@ -19,19 +18,13 @@ def setup_method(self, _): def test_show(self): common.show("Hello, world!", file=self.file, color=None) - assert [ - call.write("Hello, world!"), - call.write("\n"), - ] == self.file.mock_calls + assert [call.write("Hello, world!"), call.write("\n")] == self.file.mock_calls def test_show_after_indent(self): common.indent() common.show("|\n", file=self.file, color=None) - assert [ - call.write(" |\n"), - call.write("\n"), - ] == self.file.mock_calls + assert [call.write(" |\n"), call.write("\n")] == self.file.mock_calls def test_show_after_1_indent_2_dedent(self): common.indent() @@ -39,14 +32,10 @@ def test_show_after_1_indent_2_dedent(self): common.dedent() common.show("|\n", file=self.file, color=None) - assert [ - call.write("|\n"), - call.write("\n"), - ] == self.file.mock_calls + assert [call.write("|\n"), call.write("\n")] == self.file.mock_calls class TestShowLog: - def setup_method(self, _): _Config.indent_level = 0 _Config.verbosity = 1 @@ -55,24 +44,18 @@ def setup_method(self, _): def test_show(self): common.show("Hello, world!", log=self.log, color=None) - assert [ - call.info("Hello, world!"), - ] == self.log.mock_calls + assert [call.info("Hello, world!")] == self.log.mock_calls def test_show_errors(self): common.show("Oops", color='error', log=self.log) - expect(self.log.mock_calls) == [ - call.error("Oops"), - ] + expect(self.log.mock_calls) == [call.error("Oops")] def test_show_after_indent(self): common.indent() common.show("|\n", log=self.log, color=None) - assert [ - call.info("|"), - ] == self.log.mock_calls + assert [call.info("|")] == self.log.mock_calls def test_show_after_1_indent_2_dedent(self): common.indent() @@ -80,13 +63,10 @@ def test_show_after_1_indent_2_dedent(self): common.dedent() common.show("|\n", log=self.log, color=None) - assert [ - call.info("|"), - ] == self.log.mock_calls + assert [call.info("|")] == self.log.mock_calls class TestShowQuiet: - def setup_method(self, _): _Config.indent_level = 0 _Config.verbosity = -1 @@ -101,14 +81,12 @@ def test_show(self): def describe_show(): - def it_requries_color_with_messages(): with expect.raises(AssertionError): common.show("Hello, world!", 'foobar') def describe_style(): - def when_no_color_support(): msg = common.style("_foo_") diff --git a/gitman/tests/test_git.py b/gitman/tests/test_git.py index d04b2b97..cf9767a2 100644 --- a/gitman/tests/test_git.py +++ b/gitman/tests/test_git.py @@ -17,14 +17,17 @@ class TestGit: def test_clone(self, mock_call): """Verify the commands to set up a new reference repository.""" git.clone('git', 'mock.git', 'mock/path', cache='cache') - check_calls(mock_call, [ - "git clone --mirror mock.git " + - os.path.normpath("cache/mock.reference"), - "git clone --reference " + - os.path.normpath("cache/mock.reference") + - " mock.git " + - os.path.normpath("mock/path") - ]) + check_calls( + mock_call, + [ + "git clone --mirror mock.git " + + os.path.normpath("cache/mock.reference"), + "git clone --reference " + + os.path.normpath("cache/mock.reference") + + " mock.git " + + os.path.normpath("mock/path"), + ], + ) @patch('os.path.isdir', Mock(return_value=False)) def test_clone_without_cache(self, mock_call): @@ -32,9 +35,9 @@ def test_clone_without_cache(self, mock_call): settings.CACHE_DISABLE = True try: git.clone('git', 'mock.git', 'mock/path', cache='cache') - check_calls(mock_call, [ - "git clone mock.git " + os.path.normpath("mock/path") - ]) + check_calls( + mock_call, ["git clone mock.git " + os.path.normpath("mock/path")] + ) finally: settings.CACHE_DISABLE = False @@ -42,63 +45,78 @@ def test_clone_without_cache(self, mock_call): def test_clone_from_reference(self, mock_call): """Verify the commands to clone a Git repository from a reference.""" git.clone('git', 'mock.git', 'mock/path', cache='cache') - check_calls(mock_call, [ - "git clone --reference " + - os.path.normpath("cache/mock.reference") + - " mock.git " + - os.path.normpath("mock/path") - ]) + check_calls( + mock_call, + [ + "git clone --reference " + + os.path.normpath("cache/mock.reference") + + " mock.git " + + os.path.normpath("mock/path") + ], + ) def test_fetch(self, mock_call): """Verify the commands to fetch from a Git repository.""" git.fetch('git', 'mock.git', 'mock/path') - check_calls(mock_call, [ - "git remote set-url origin mock.git", - "git fetch --tags --force --prune origin", - ]) + check_calls( + mock_call, + [ + "git remote set-url origin mock.git", + "git fetch --tags --force --prune origin", + ], + ) def test_fetch_rev(self, mock_call): """Verify the commands to fetch from a Git repository w/ rev.""" git.fetch('git', 'mock.git', 'mock/path', 'mock-rev') - check_calls(mock_call, [ - "git remote set-url origin mock.git", - "git fetch --tags --force --prune origin mock-rev", - ]) + check_calls( + mock_call, + [ + "git remote set-url origin mock.git", + "git fetch --tags --force --prune origin mock-rev", + ], + ) def test_fetch_rev_sha(self, mock_call): """Verify the commands to fetch from a Git repository w/ SHA.""" git.fetch('git', 'mock.git', 'mock/path', 'abcdef1234' * 4) - check_calls(mock_call, [ - "git remote set-url origin mock.git", - "git fetch --tags --force --prune origin", - ]) + check_calls( + mock_call, + [ + "git remote set-url origin mock.git", + "git fetch --tags --force --prune origin", + ], + ) def test_fetch_rev_revparse(self, mock_call): """Verify the commands to fetch from a Git repository w/ rev-parse.""" - git.fetch('git', 'mock.git', 'mock/path', - 'master@{2015-02-12 18:30:00}') - check_calls(mock_call, [ - "git remote set-url origin mock.git", - "git fetch --tags --force --prune origin", - ]) + git.fetch('git', 'mock.git', 'mock/path', 'master@{2015-02-12 18:30:00}') + check_calls( + mock_call, + [ + "git remote set-url origin mock.git", + "git fetch --tags --force --prune origin", + ], + ) def test_valid(self, mock_call): """Verify the commands to check for a working tree.""" git.valid() - check_calls(mock_call, [ - "git rev-parse --is-inside-work-tree", - ]) + check_calls(mock_call, ["git rev-parse --is-inside-work-tree"]) def test_changes(self, mock_call): """Verify the commands to check for uncommitted changes.""" git.changes('git', include_untracked=True) - check_calls(mock_call, [ - # based on: http://stackoverflow.com/questions/3878624 - "git update-index -q --refresh", - "git diff-index --quiet HEAD", - "git ls-files --others --exclude-standard", - "git status", # used for displaying the overall status - ]) + check_calls( + mock_call, + [ + # based on: http://stackoverflow.com/questions/3878624 + "git update-index -q --refresh", + "git diff-index --quiet HEAD", + "git ls-files --others --exclude-standard", + "git status", # used for displaying the overall status + ], + ) def test_changes_false(self, _): """Verify the absence of changes can be detected.""" @@ -123,46 +141,58 @@ def test_changes_true_when_uncommitted(self, _): def test_update(self, mock_call): """Verify the commands to update a working tree to a revision.""" git.update('git', 'mock.git', 'mock/path', rev='mock_rev') - check_calls(mock_call, [ - "git stash", - "git clean --force -d -x", - "git checkout --force mock_rev", - "git branch --set-upstream-to origin/mock_rev", - ]) + check_calls( + mock_call, + [ + "git stash", + "git clean --force -d -x", + "git checkout --force mock_rev", + "git branch --set-upstream-to origin/mock_rev", + ], + ) def test_update_branch(self, mock_call): """Verify the commands to update a working tree to a branch.""" - git.update('git', 'mock.git', 'mock/path', - fetch=True, rev='mock_branch') - check_calls(mock_call, [ - "git stash", - "git clean --force -d -x", - "git checkout --force mock_branch", - "git branch --set-upstream-to origin/mock_branch", - "git pull --ff-only --no-rebase", - ]) + git.update('git', 'mock.git', 'mock/path', fetch=True, rev='mock_branch') + check_calls( + mock_call, + [ + "git stash", + "git clean --force -d -x", + "git checkout --force mock_branch", + "git branch --set-upstream-to origin/mock_branch", + "git pull --ff-only --no-rebase", + ], + ) def test_update_no_clean(self, mock_call): git.update('git', 'mock.git', 'mock/path', clean=False, rev='mock_rev') - check_calls(mock_call, [ - "git stash", - "git checkout --force mock_rev", - "git branch --set-upstream-to origin/mock_rev", - ]) + check_calls( + mock_call, + [ + "git stash", + "git checkout --force mock_rev", + "git branch --set-upstream-to origin/mock_rev", + ], + ) def test_update_revparse(self, mock_call): """Verify the commands to update a working tree to a rev-parse.""" mock_call.return_value = ["abc123"] - git.update('git', 'mock.git', 'mock/path', - rev='mock_branch@{2015-02-12 18:30:00}') - check_calls(mock_call, [ - "git stash", - "git clean --force -d -x", - "git checkout --force mock_branch", - "git rev-list -n 1 --before='2015-02-12 18:30:00' mock_branch", - "git checkout --force abc123", - "git branch --set-upstream-to origin/abc123", - ]) + git.update( + 'git', 'mock.git', 'mock/path', rev='mock_branch@{2015-02-12 18:30:00}' + ) + check_calls( + mock_call, + [ + "git stash", + "git clean --force -d -x", + "git checkout --force mock_branch", + "git rev-list -n 1 --before='2015-02-12 18:30:00' mock_branch", + "git checkout --force abc123", + "git branch --set-upstream-to origin/abc123", + ], + ) def test_get_url(self, mock_call): """Verify the commands to get the current repository's URL.""" diff --git a/gitman/tests/test_models_config.py b/gitman/tests/test_models_config.py index 61ef8671..4abdfef2 100644 --- a/gitman/tests/test_models_config.py +++ b/gitman/tests/test_models_config.py @@ -11,7 +11,6 @@ class TestConfig: - def test_init_defaults(self): """Verify a config has a default filename and location.""" config = Config('mock/root') @@ -105,32 +104,29 @@ def test_install_with_depth_2(self): def describe_config(): - @pytest.fixture def config(): return Config('m/root', 'm.ext', 'm/location') def describe_get_path(): - def it_defaults_to_sources_location(config): - expect(config.get_path()) == \ - os.path.normpath("m/root/m/location") + expect(config.get_path()) == os.path.normpath("m/root/m/location") def it_can_get_the_config_path(config): - expect(config.get_path('__config__')) == \ - os.path.normpath("m/root/m.ext") + expect(config.get_path('__config__')) == os.path.normpath("m/root/m.ext") def it_can_get_log_path(config): - expect(config.get_path('__log__')) == \ - os.path.normpath("m/root/m/location/gitman.log") + expect(config.get_path('__log__')) == os.path.normpath( + "m/root/m/location/gitman.log" + ) def it_can_get_dependency_path(config): - expect(config.get_path('foobar')) == \ - os.path.normpath("m/root/m/location/foobar") + expect(config.get_path('foobar')) == os.path.normpath( + "m/root/m/location/foobar" + ) class TestLoad: - def test_load_from_directory_with_config_file(self): config = load_config(FILES) diff --git a/gitman/tests/test_models_source.py b/gitman/tests/test_models_source.py index 1f5d42dc..1a88c621 100644 --- a/gitman/tests/test_models_source.py +++ b/gitman/tests/test_models_source.py @@ -14,7 +14,6 @@ def source(): class TestSource: - def test_init_defaults(self): """Verify a source has a default revision.""" source = Source('git', 'http://example.com/foo/bar.git') @@ -47,8 +46,7 @@ def test_init_error(self): def test_repr(self, source): """Verify sources can be represented.""" - assert "" == \ - repr(source) + assert "" == repr(source) def test_repr_no_link(self, source): """Verify sources can be represented.""" diff --git a/gitman/tests/test_plugin.py b/gitman/tests/test_plugin.py index 87342dd2..45ca3579 100644 --- a/gitman/tests/test_plugin.py +++ b/gitman/tests/test_plugin.py @@ -17,9 +17,14 @@ def test_install(self, mock_commands): plugin.main([]) assert [ - call.install(root=None, depth=None, - clean=False, fetch=True, force=False, - skip_changes=False), + call.install( + root=None, + depth=None, + clean=False, + fetch=True, + force=False, + skip_changes=False, + ), call.install().__bool__(), # command status check ] == mock_commands.mock_calls @@ -31,9 +36,15 @@ def test_update(self, mock_commands): plugin.main(['--update', '--clean']) assert [ - call.update(root=None, depth=None, - clean=True, force=False, recurse=False, lock=True, - skip_changes=False), + call.update( + root=None, + depth=None, + clean=True, + force=False, + recurse=False, + lock=True, + skip_changes=False, + ), call.update().__bool__(), # command status check ] == mock_commands.mock_calls @@ -45,9 +56,15 @@ def test_update_recursive(self, mock_commands): plugin.main(['--update', '--all']) assert [ - call.update(root=None, depth=None, - clean=False, force=False, recurse=True, lock=True, - skip_changes=False), + call.update( + root=None, + depth=None, + clean=False, + force=False, + recurse=True, + lock=True, + skip_changes=False, + ), call.update().__bool__(), # command status check ] == mock_commands.mock_calls @@ -59,9 +76,15 @@ def test_update_no_lock(self, mock_commands): plugin.main(['--update', '--skip-lock']) assert [ - call.update(root=None, depth=None, - clean=False, force=False, recurse=False, lock=False, - skip_changes=False), + call.update( + root=None, + depth=None, + clean=False, + force=False, + recurse=False, + lock=False, + skip_changes=False, + ), call.update().__bool__(), # command status check ] == mock_commands.mock_calls @@ -73,9 +96,15 @@ def test_update_skip_changes(self, mock_commands): plugin.main(['--update', '--skip-changes']) assert [ - call.update(root=None, depth=None, - clean=False, force=False, recurse=False, lock=True, - skip_changes=True), + call.update( + root=None, + depth=None, + clean=False, + force=False, + recurse=False, + lock=True, + skip_changes=True, + ), call.update().__bool__(), # command status check ] == mock_commands.mock_calls @@ -87,8 +116,7 @@ def test_list(self, mock_commands): plugin.main(['--list']) assert [ - call.display(root=None, depth=None, - allow_dirty=True), + call.display(root=None, depth=None, allow_dirty=True), call.display().__bool__(), # command status check ] == mock_commands.mock_calls diff --git a/gitman/tests/test_shell.py b/gitman/tests/test_shell.py index 4c2acfd8..1214c387 100644 --- a/gitman/tests/test_shell.py +++ b/gitman/tests/test_shell.py @@ -70,10 +70,7 @@ def test_ln_missing_parent(self, mock_call): if os.name == 'nt': check_calls(mock_call, []) else: - check_calls(mock_call, [ - "mkdir -p mock", - "ln -s mock/target mock/source", - ]) + check_calls(mock_call, ["mkdir -p mock", "ln -s mock/target mock/source"]) @patch('os.path.isfile', Mock(return_value=True)) def test_rm_file(self, mock_call): diff --git a/gitman/tests/test_system.py b/gitman/tests/test_system.py index 53f23b9f..44d9e131 100644 --- a/gitman/tests/test_system.py +++ b/gitman/tests/test_system.py @@ -8,7 +8,6 @@ def describe_launch(): - @patch('platform.system', Mock(return_value="Windows")) @patch('gitman.system._launch_windows') def it_opens_files(startfile): diff --git a/mkdocs.yml b/mkdocs.yml index be7d0d4d..568530a6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,7 +5,7 @@ repo_url: https://github.com/jacebrowning/gitman theme: readthedocs -pages: +nav: - Home: index.md - Setup: - Git: setup/git.md diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..8739c887 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,653 @@ +[[package]] +category = "dev" +description = "Python graph (network) package" +name = "altgraph" +optional = false +python-versions = "*" +version = "0.16.1" + +[[package]] +category = "dev" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" +optional = false +python-versions = "*" +version = "1.4.3" + +[[package]] +category = "dev" +description = "An abstract syntax tree for Python with inference support." +name = "astroid" +optional = false +python-versions = ">=3.4.*" +version = "2.1.0" + +[package.dependencies] +lazy-object-proxy = "*" +six = "*" +wrapt = "*" + +[package.dependencies.typed-ast] +python = "<3.7" +version = "*" + +[[package]] +category = "dev" +description = "Atomic file writes." +name = "atomicwrites" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.1" + +[[package]] +category = "dev" +description = "Classes Without Boilerplate" +name = "attrs" +optional = false +python-versions = "*" +version = "18.2.0" + +[[package]] +category = "dev" +description = "A backport of the get_terminal_size function from Python 3.3's shutil." +name = "backports.shutil-get-terminal-size" +optional = false +python-versions = "*" +version = "1.0.0" + +[[package]] +category = "dev" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6" +version = "18.9b0" + +[package.dependencies] +appdirs = "*" +attrs = ">=17.4.0" +click = ">=6.5" +toml = ">=0.9.4" + +[[package]] +category = "dev" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2018.11.29" + +[[package]] +category = "dev" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] +category = "dev" +description = "Composable command line interface toolkit" +name = "click" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "7.0" + +[[package]] +category = "dev" +description = "Cross-platform colored terminal text." +name = "colorama" +optional = false +python-versions = "*" +version = "0.3.9" + +[[package]] +category = "dev" +description = "Code coverage measurement for Python" +name = "coverage" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" +version = "4.5.2" + +[[package]] +category = "dev" +description = "A place to track your code coverage metrics." +name = "coveragespace" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.1" + +[package.dependencies] +"backports.shutil-get-terminal-size" = ">=1.0,<2.0" +colorama = ">=0.3,<0.4" +coverage = ">=4.0,<5.0" +docopt = ">=0.6,<0.7" +requests = ">=2.0,<3.0" + +[[package]] +category = "dev" +description = "Pythonic argument parser, that will make you smile" +name = "docopt" +optional = false +python-versions = "*" +version = "0.6.2" + +[[package]] +category = "dev" +description = "Let your Python tests travel through time" +name = "freezegun" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.3.11" + +[package.dependencies] +python-dateutil = ">=1.0,<2.0 || >2.0" +six = "*" + +[[package]] +category = "dev" +description = "Clean single-source support for Python 3 and 2" +name = "future" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "0.17.1" + +[[package]] +category = "dev" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.8" + +[[package]] +category = "dev" +description = "A Python utility / library to sort Python imports." +name = "isort" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "4.3.4" + +[[package]] +category = "dev" +description = "A small but fast and easy to use stand-alone template engine written in pure python." +name = "jinja2" +optional = false +python-versions = "*" +version = "2.10" + +[package.dependencies] +MarkupSafe = ">=0.23" + +[[package]] +category = "dev" +description = "A fast and thorough lazy object proxy." +name = "lazy-object-proxy" +optional = false +python-versions = "*" +version = "1.3.1" + +[[package]] +category = "dev" +description = "Python LiveReload is an awesome tool for web developers" +name = "livereload" +optional = false +python-versions = "*" +version = "2.6.0" + +[package.dependencies] +six = "*" +tornado = "*" + +[[package]] +category = "dev" +description = "Thread-based interface to file system observation primitives." +marker = "sys_platform == \"darwin\"" +name = "macfsevents" +optional = false +python-versions = "*" +version = "0.8.1" + +[[package]] +category = "dev" +description = "Mach-O header analysis and editing" +name = "macholib" +optional = false +python-versions = "*" +version = "1.11" + +[package.dependencies] +altgraph = ">=0.15" + +[[package]] +category = "dev" +description = "Python implementation of Markdown." +name = "markdown" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "3.0.1" + +[[package]] +category = "dev" +description = "Safely add untrusted strings to HTML/XML markup." +name = "markupsafe" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.1.0" + +[[package]] +category = "dev" +description = "McCabe checker, plugin for flake8" +name = "mccabe" +optional = false +python-versions = "*" +version = "0.6.1" + +[[package]] +category = "dev" +description = "Project documentation with Markdown." +name = "mkdocs" +optional = false +python-versions = ">=2.7.9,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.0.4" + +[package.dependencies] +Jinja2 = ">=2.7.1" +Markdown = ">=2.3.1" +PyYAML = ">=3.10" +click = ">=3.3" +livereload = ">=2.5.1" +tornado = ">=5.0" + +[[package]] +category = "dev" +description = "More routines for operating on iterables, beyond itertools" +name = "more-itertools" +optional = false +python-versions = "*" +version = "4.3.0" + +[package.dependencies] +six = ">=1.0.0,<2.0.0" + +[[package]] +category = "dev" +description = "Optional static typing for Python" +name = "mypy" +optional = false +python-versions = "*" +version = "0.650" + +[package.dependencies] +mypy-extensions = ">=0.4.0,<0.5.0" +typed-ast = ">=1.1.0,<1.2.0" + +[[package]] +category = "dev" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +name = "mypy-extensions" +optional = false +python-versions = "*" +version = "0.4.1" + +[[package]] +category = "dev" +description = "nose extends unittest to make testing easier" +name = "nose" +optional = false +python-versions = "*" +version = "1.3.7" + +[[package]] +category = "main" +description = "parse() is the opposite of format()" +name = "parse" +optional = false +python-versions = "*" +version = "1.8.4" + +[[package]] +category = "dev" +description = "Python PE parsing module" +name = "pefile" +optional = false +python-versions = "*" +version = "2018.8.8" + +[package.dependencies] +future = "*" + +[[package]] +category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.8.0" + +[[package]] +category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.7.0" + +[[package]] +category = "dev" +description = "Python docstring style checker" +name = "pydocstyle" +optional = false +python-versions = "*" +version = "3.0.0" + +[package.dependencies] +six = "*" +snowballstemmer = "*" + +[[package]] +category = "dev" +description = "Pygments is a syntax highlighting package written in Python." +name = "pygments" +optional = false +python-versions = "*" +version = "2.3.1" + +[[package]] +category = "dev" +description = "PyInstaller bundles a Python application and all its dependencies into a single package." +name = "pyinstaller" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.4" + +[package.dependencies] +altgraph = "*" +macholib = ">=1.8" +pefile = ">=2017.8.1" +setuptools = "*" + +[[package]] +category = "dev" +description = "python code static checker" +name = "pylint" +optional = false +python-versions = ">=3.4.*" +version = "2.2.2" + +[package.dependencies] +astroid = ">=2.0.0" +colorama = "*" +isort = ">=4.2.5" +mccabe = "*" + +[[package]] +category = "dev" +description = "Python Wrapper for Mac OS 10.10 Notification Center" +marker = "sys_platform == \"darwin\"" +name = "pync" +optional = false +python-versions = "*" +version = "2.0.3" + +[package.dependencies] +python-dateutil = ">=2.0" + +[[package]] +category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.10.1" + +[package.dependencies] +atomicwrites = ">=1.0" +attrs = ">=17.4.0" +colorama = "*" +more-itertools = ">=4.0.0" +pluggy = ">=0.7" +py = ">=1.5.0" +setuptools = "*" +six = ">=1.10.0" + +[[package]] +category = "dev" +description = "Pytest plugin for measuring coverage." +name = "pytest-cov" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.6.0" + +[package.dependencies] +coverage = ">=4.4" +pytest = ">=2.9" + +[[package]] +category = "dev" +description = "Describe-style plugin for pytest" +name = "pytest-describe" +optional = false +python-versions = "*" +version = "0.11.1" + +[package.dependencies] +pytest = ">=2.6.0" + +[[package]] +category = "dev" +description = "Better testing with expecter and pytest." +name = "pytest-expecter" +optional = false +python-versions = "*" +version = "1.3" + +[[package]] +category = "dev" +description = "py.test plugin to randomize tests" +name = "pytest-random" +optional = false +python-versions = "*" +version = "0.02" + +[package.dependencies] +pytest = ">=2.2.3" + +[[package]] +category = "dev" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.7.5" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "dev" +description = "console colouring for python" +name = "python-termstyle" +optional = false +python-versions = "*" +version = "0.1.10" + +[package.dependencies] +setuptools = "*" + +[[package]] +category = "main" +description = "YAML parser and emitter for Python" +name = "pyyaml" +optional = false +python-versions = "*" +version = "3.13" + +[[package]] +category = "dev" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.21.0" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<3.1.0" +idna = ">=2.5,<2.9" +urllib3 = ">=1.21.1,<1.25" + +[[package]] +category = "main" +description = "Simple, fast, extensible JSON encoder/decoder for Python" +name = "simplejson" +optional = false +python-versions = "*" +version = "3.16.0" + +[[package]] +category = "dev" +description = "Python 2 and 3 compatibility utilities" +name = "six" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "1.12.0" + +[[package]] +category = "dev" +description = "An automatic test runner. Supports nose out of the box." +name = "sniffer" +optional = false +python-versions = "*" +version = "0.4.0" + +[package.dependencies] +colorama = "*" +nose = "*" +python-termstyle = "*" + +[[package]] +category = "dev" +description = "This package provides 16 stemmer algorithms (15 + Poerter English stemmer) generated from Snowball algorithms." +name = "snowballstemmer" +optional = false +python-versions = "*" +version = "1.2.1" + +[[package]] +category = "dev" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.0" + +[[package]] +category = "dev" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +name = "tornado" +optional = false +python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, != 3.3.*" +version = "5.1.1" + +[[package]] +category = "dev" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.1.1" + +[[package]] +category = "dev" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" +version = "1.24.1" + +[[package]] +category = "dev" +description = "Module for decorators, wrappers and monkey patching." +name = "wrapt" +optional = false +python-versions = "*" +version = "1.10.11" + +[[package]] +category = "main" +description = "Automatic object-YAML mapping for Python." +name = "yorm" +optional = false +python-versions = "*" +version = "1.6" + +[package.dependencies] +PyYAML = ">=3.13,<4" +parse = ">=1.8.0,<1.9.0" +simplejson = ">=3.8,<4.0" + +[metadata] +content-hash = "3e412bc2d9a2e99db9290c27f3977f3eec75e8cbb89eefd7d8498c5b89b2c898" +python-versions = "^3.6" + +[metadata.hashes] +altgraph = ["d6814989f242b2b43025cba7161fc1b8fb487a62cd49c49245d6fd01c18ac997", "ddf5320017147ba7b810198e0b6619bd7b5563aa034da388cea8546b877f9b0c"] +appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"] +astroid = ["35b032003d6a863f5dcd7ec11abd5cd5893428beaa31ab164982403bcb311f22", "6a5d668d7dc69110de01cdf7aeec69a679ef486862a0850cc0fd5571505b6b7e"] +atomicwrites = ["0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", "ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"] +attrs = ["10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", "ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"] +"backports.shutil-get-terminal-size" = ["0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", "713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80"] +black = ["817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739", "e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"] +certifi = ["47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", "993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"] +chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"] +click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] +colorama = ["463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", "48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"] +coverage = ["06123b58a1410873e22134ca2d88bd36680479fe354955b3579fb8ff150e4d27", "09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", "0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", "0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", "0d34245f824cc3140150ab7848d08b7e2ba67ada959d77619c986f2062e1f0e8", "10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", "1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", "1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", "258b21c5cafb0c3768861a6df3ab0cfb4d8b495eee5ec660e16f928bf7385390", "2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", "3ad59c84c502cd134b0088ca9038d100e8fb5081bbd5ccca4863f3804d81f61d", "447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", "46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", "4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", "510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", "5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", "5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", "5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", "6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", "6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", "71afc1f5cd72ab97330126b566bbf4e8661aab7449f08895d21a5d08c6b051ff", "7349c27128334f787ae63ab49d90bf6d47c7288c63a0a5dfaa319d4b4541dd2c", "77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", "828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", "859714036274a75e6e57c7bab0c47a4602d2a8cfaaa33bbdb68c8359b2ed4f5c", "85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", "869ef4a19f6e4c6987e18b315721b8b971f7048e6eaea29c066854242b4e98d9", "8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", "977e2d9a646773cc7428cdd9a34b069d6ee254fadfb4d09b3f430e95472f3cf3", "99bd767c49c775b79fdcd2eabff405f1063d9d959039c0bdd720527a7738748a", "a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", "aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", "ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", "b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", "bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", "c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", "d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", "d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", "da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", "ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", "ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9"] +coveragespace = ["498b54ec158a19e1f5647da681dc77fd9d17df11ecff1253d60ac7970209f6e5", "7c5ce4641e0f995b9be0e8b53401fd7b6d17db1b8c23bfd06f0c845ad0de5b5f"] +docopt = ["49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"] +freezegun = ["6cb82b276f83f2acce67f121dc2656f4df26c71e32238334eb071170b892a278", "e839b43bfbe8158b4d62bb97e6313d39f3586daf48e1314fb1083d2ef17700da"] +future = ["67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"] +idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"] +isort = ["1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", "b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"] +jinja2 = ["74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", "f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"] +lazy-object-proxy = ["0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", "1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", "209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", "27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", "27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", "2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", "2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", "320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", "50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", "5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", "61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", "6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", "7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", "7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", "7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", "7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", "81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", "933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", "94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", "ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", "bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", "cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", "d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", "ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", "e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", "e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", "e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", "eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", "f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b"] +livereload = ["29cadfabcedd12eed792e0131991235b9d4764d4474bed75cf525f57109ec0a2", "e632a6cd1d349155c1d7f13a65be873b38f43ef02961804a1bba8d817fa649a7"] +macfsevents = ["1324b66b356051de662ba87d84f73ada062acd42b047ed1246e60a449f833e10"] +macholib = ["ac02d29898cf66f27510d8f39e9112ae00590adb4a48ec57b25028d6962b1ae1", "c4180ffc6f909bf8db6cd81cff4b6f601d575568f4d5dee148c830e9851eb9db"] +markdown = ["c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa", "d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c"] +markupsafe = ["048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", "130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", "19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", "1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", "1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", "1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", "1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", "31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", "3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", "4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", "525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", "52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", "52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", "5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", "5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", "5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", "7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", "83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", "857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", "98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", "bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", "d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", "e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", "edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", "efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", "f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", "f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", "fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"] +mccabe = ["ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"] +mkdocs = ["17d34329aad75d5de604b9ed4e31df3a4d235afefdc46ce7b1964fddb2e1e939", "8cc8b38325456b9e942c981a209eaeb1e9f3f77b493ad755bfef889b9c8d356a"] +more-itertools = ["c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", "c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", "fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d"] +mypy = ["12d965c9c4e8a625673aec493162cf390e66de12ef176b1f4821ac00d55f3ab3", "38d5b5f835a81817dcc0af8d155bce4e9aefa03794fe32ed154d6612e83feafa"] +mypy-extensions = ["37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", "b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e"] +nose = ["9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", "dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", "f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"] +parse = ["c3cdf6206f22aeebfa00e5b954fcfea13d1b2dc271c75806b6025b94fb490939"] +pefile = ["4c5b7e2de0c8cb6c504592167acf83115cbbde01fe4a507c16a1422850e86cd6"] +pluggy = ["447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095", "bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f"] +py = ["bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", "e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"] +pydocstyle = ["2258f9b0df68b97bf3a6c29003edc5238ff8879f1efb6f1999988d934e432bd8", "5741c85e408f9e0ddf873611085e819b809fca90b619f5fd7f34bd4959da3dd4", "ed79d4ec5e92655eccc21eb0c6cf512e69512b4a97d215ace46d17e4990f2039"] +pygments = ["5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", "e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"] +pyinstaller = ["a5a6e04a66abfcf8761e89a2ebad937919c6be33a7b8963e1a961b55cb35986b"] +pylint = ["689de29ae747642ab230c6d37be2b969bf75663176658851f456619aacf27492", "771467c434d0d9f081741fec1d64dfb011ed26e65e12a28fe06ca2f61c4d556c"] +pync = ["38b9e61735a3161f9211a5773c5f5ea698f36af4ff7f77fa03e8d1ff0caa117f"] +pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"] +pytest-cov = ["513c425e931a0344944f84ea47f3956be0e416d95acbd897a44970c8d926d5d7", "e360f048b7dae3f2f2a9a4d067b2dd6b6a015d384d1577c994a43f3f7cbad762"] +pytest-describe = ["bd6be131452b7822c872735ffe53ce3931b3b80cbbad1647c2b482cc9ef3d00e"] +pytest-expecter = ["1c8e9ab98ddd576436b61a7ba61ea11cfa5a3fc6b00288ce9e91e9dd770daf19", "27c93dfe87e2f4d28c525031be68d3f89457e3315241d97ee15f7689544e0e37"] +pytest-random = ["92f25db8c5d9ffc20d90b51997b914372d6955cb9cf1f6ead45b90514fc0eddd"] +python-dateutil = ["063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", "88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"] +python-termstyle = ["6faf42ba42f2826c38cf70dacb3ac51f248a418e48afc0e36593df11cf3ab1d2", "f42a6bb16fbfc5e2c66d553e7ad46524ea833872f75ee5d827c15115fafc94e2"] +pyyaml = ["3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", "3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", "40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", "558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", "a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", "aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", "bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", "d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", "d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", "e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", "e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"] +requests = ["502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", "7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"] +simplejson = ["067a7177ddfa32e1483ba5169ebea1bc2ea27f224853211ca669325648ca5642", "2b8cb601d9ba0381499db719ccc9dfbb2fbd16013f5ff096b1a68a4775576a04", "2c139daf167b96f21542248f8e0a06596c9b9a7a41c162cc5c9ee9f3833c93cd", "2fc546e6af49fb45b93bbe878dea4c48edc34083729c0abd09981fe55bdf7f91", "354fa32b02885e6dae925f1b5bbf842c333c1e11ea5453ddd67309dc31fdb40a", "37e685986cf6f8144607f90340cff72d36acf654f3653a6c47b84c5c38d00df7", "3af610ee72efbe644e19d5eaad575c73fb83026192114e5f6719f4901097fce2", "3b919fc9cf508f13b929a9b274c40786036b31ad28657819b3b9ba44ba651f50", "3dd289368bbd064974d9a5961101f080e939cbe051e6689a193c99fb6e9ac89b", "491de7acc423e871a814500eb2dcea8aa66c4a4b1b4825d18f756cdf58e370cb", "495511fe5f10ccf4e3ed4fc0c48318f533654db6c47ecbc970b4ed215c791968", "65b41a5cda006cfa7c66eabbcf96aa704a6be2a5856095b9e2fd8c293bad2b46", "6c3258ffff58712818a233b9737fe4be943d306c40cf63d14ddc82ba563f483a", "75e3f0b12c28945c08f54350d91e624f8dd580ab74fd4f1bbea54bc6b0165610", "79b129fe65fdf3765440f7a73edaffc89ae9e7885d4e2adafe6aa37913a00fbb", "b1f329139ba647a9548aa05fb95d046b4a677643070dc2afc05fa2e975d09ca5", "c206f47cbf9f32b573c9885f0ec813d2622976cf5effcf7e472344bc2e020ac1", "d8e238f20bcf70063ee8691d4a72162bcec1f4c38f83c93e6851e72ad545dabb", "ee9625fc8ee164902dfbb0ff932b26df112da9f871c32f0f9c1bcf20c350fe2a", "fb2530b53c28f0d4d84990e945c2ebb470edb469d63e389bf02ff409012fe7c5", "feadb95170e45f439455354904768608e356c5b174ca30b3d11b0e3f24b5c0df"] +six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] +sniffer = ["e8a0daa4c51dff3d00482b45dc9b978159100a8d5a7df327c28ed96586559970", "e90c1ad4bd3c31a5fad8e03d45dfc83377b31420aa0779f17280c817ce0c9dd8"] +snowballstemmer = ["919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", "9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"] +toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] +tornado = ["0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d", "4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409", "732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f", "8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f", "8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5", "d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb", "e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"] +typed-ast = ["0555eca1671ebe09eb5f2176723826f6f44cca5060502fea259de9b0e893ab53", "0ca96128ea66163aea13911c9b4b661cb345eb729a20be15c034271360fc7474", "16ccd06d614cf81b96de42a37679af12526ea25a208bce3da2d9226f44563868", "1e21ae7b49a3f744958ffad1737dfbdb43e1137503ccc59f4e32c4ac33b0bd1c", "37670c6fd857b5eb68aa5d193e14098354783b5138de482afa401cc2644f5a7f", "46d84c8e3806619ece595aaf4f37743083f9454c9ea68a517f1daa05126daf1d", "5b972bbb3819ece283a67358103cc6671da3646397b06e7acea558444daf54b2", "6306ffa64922a7b58ee2e8d6f207813460ca5a90213b4a400c2e730375049246", "6cb25dc95078931ecbd6cbcc4178d1b8ae8f2b513ae9c3bd0b7f81c2191db4c6", "7e19d439fee23620dea6468d85bfe529b873dace39b7e5b0c82c7099681f8a22", "7f5cd83af6b3ca9757e1127d852f497d11c7b09b4716c355acfbebf783d028da", "81e885a713e06faeef37223a5b1167615db87f947ecc73f815b9d1bbd6b585be", "94af325c9fe354019a29f9016277c547ad5d8a2d98a02806f27a7436b2da6735", "b1e5445c6075f509d5764b84ce641a1535748801253b97f3b7ea9d948a22853a", "cb061a959fec9a514d243831c514b51ccb940b58a5ce572a4e209810f2507dcf", "cc8d0b703d573cbabe0d51c9d68ab68df42a81409e4ed6af45a04a95484b96a5", "da0afa955865920edb146926455ec49da20965389982f91e926389666f5cf86a", "dc76738331d61818ce0b90647aedde17bbba3d3f9e969d83c1d9087b4f978862", "e7ec9a1445d27dbd0446568035f7106fa899a36f55e52ade28020f7b3845180d", "f741ba03feb480061ab91a465d1a3ed2d40b52822ada5b4017770dfcb88f839f", "fe800a58547dd424cd286b7270b967b5b3316b993d86453ede184a17b5a6b17d"] +urllib3 = ["61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"] +wrapt = ["d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6"] +yorm = ["863674ad8e1cfe5b8aa42e333039c0f54d591bb0d28ff9d4299b8109a02239f9", "aa540ccb087a9c3a8eac385073a2da1c5362591b45dec7a9a2cb212e898d9f84"] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..cb37d13b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,94 @@ +[tool.poetry] + +name = "gitman" +version = "1.6a4" +description = "A language-agnostic dependency manager using Git." + +license = "MIT" + +authors = ["Jace Browning "] + +readme = "README.md" + +homepage = "https://pypi.org/project/gitman" +documentation = "https://gitman.readthedocs.io" +repository = "https://github.com/jacebrowning/gitman" + +keywords = [ + "git", + "version control", + "build systems", + "dependency management", + "submodules", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Software Development", + "Topic :: Software Development :: Build Tools", + "Topic :: Software Development :: Version Control", + "Topic :: System :: Software Distribution", +] + +[tool.poetry.dependencies] + +python = "^3.6" + +YORM = "^1.3" + +[tool.poetry.dev-dependencies] + +# Formatters +black = "=18.9b0" +isort = "=4.3.4" + +# Linters +mypy = "*" +pydocstyle = "*" +pylint = "^2.0" + +# Testing +pytest = "^3.3" +pytest-cov = "*" +pytest-describe = "*" +pytest-expecter = "*" +pytest-random = "*" +freezegun = "*" + +# Reports +coveragespace = "*" + +# Documentation +mkdocs = "^1.0" +pygments = "*" + +# Tooling +pyinstaller = "*" +sniffer = "*" +MacFSEvents = { version = "*", platform = "darwin" } +pync = { version = "*", platform = "darwin" } + +[tool.poetry.scripts] + +gitman = "gitman.cli:main" +git-deps = "gitman.plugin:main" + +gdm = "gitman.cli:main" # legacy entry point + +[tool.black] + +py36 = true +skip-string-normalization = true + +[build-system] + +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/scent.py b/scent.py index ab6b337b..f003eebf 100644 --- a/scent.py +++ b/scent.py @@ -1,12 +1,9 @@ """Configuration file for sniffer.""" -# pylint: disable=superfluous-parens,bad-continuation,unpacking-non-sequence -import subprocess import time +import subprocess -from sniffer.api import file_validator, runnable, select_runnable - - +from sniffer.api import select_runnable, file_validator, runnable try: from pync import Notifier except ImportError: diff --git a/setup.py b/setup.py deleted file mode 100644 index 8b996779..00000000 --- a/setup.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python - -import os -import sys - -import setuptools - - -PACKAGE_NAME = 'gitman' -MINIMUM_PYTHON_VERSION = '3.5' - - -def check_python_version(): - """Exit when the Python version is too low.""" - if sys.version < MINIMUM_PYTHON_VERSION: - sys.exit("Python {0}+ is required.".format(MINIMUM_PYTHON_VERSION)) - - -def read_package_variable(key, filename='__init__.py'): - """Read the value of a variable from the package without importing.""" - module_path = os.path.join(PACKAGE_NAME, filename) - with open(module_path) as module: - for line in module: - parts = line.strip().split(' ', 2) - if parts[:-1] == [key, '=']: - return parts[-1].strip("'") - sys.exit("'%s' not found in '%s'", key, module_path) - - -def build_description(): - """Build a description for the project from documentation files.""" - readme = open("README.md").read() - changelog = open("CHANGELOG.md").read() - return readme + '\n' + changelog - - -check_python_version() - -setuptools.setup( - name=read_package_variable('__project__'), - version=read_package_variable('__version__'), - - description=read_package_variable('DESCRIPTION'), - url='https://github.com/jacebrowning/gitman', - author='Jace Browning', - author_email='jacebrowning@gmail.com', - - packages=setuptools.find_packages(), - - entry_points={'console_scripts': [ - read_package_variable('CLI') + ' = gitman.cli:main', - 'git-' + read_package_variable('PLUGIN') + ' = gitman.plugin:main', - # Legacy entry points: - 'gdm = gitman.cli:main', - ]}, - - long_description=build_description(), - long_description_content_type='text/markdown', - license='MIT', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Topic :: Software Development', - 'Topic :: Software Development :: Build Tools', - 'Topic :: Software Development :: Version Control', - 'Topic :: System :: Software Distribution', - ], - - install_requires=[ - 'YORM~=1.3', - ], -) diff --git a/tests/__init__.py b/tests/__init__.py index 96f579f0..250ed9e4 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,4 +3,4 @@ try: from IPython.terminal.debugger import TerminalPdb as Debugger except ImportError: - from pdb import Pdb as Debugger + from pdb import Pdb as Debugger # type: ignore diff --git a/tests/test_api.py b/tests/test_api.py index 64aa78a1..ae2dffed 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -77,13 +77,13 @@ def config(): def describe_init(): - def it_creates_a_new_config_file(tmpdir): tmpdir.chdir() expect(gitman.init()) == True - expect(Config().__mapper__.text) == strip(""" + expect(Config().__mapper__.text) == strip( + """ location: gitman_sources sources: - name: sample_dependency @@ -105,7 +105,8 @@ def it_creates_a_new_config_file(tmpdir): link: scripts: - - """) + """ + ) def it_does_not_modify_existing_config_file(config): expect(gitman.init()) == False @@ -114,7 +115,6 @@ def it_does_not_modify_existing_config_file(config): def describe_install(): - def it_creates_missing_directories(config): shell.rm(config.location) @@ -128,7 +128,8 @@ def it_should_not_modify_config(config): expect(config.__mapper__.text) == CONFIG def it_merges_sources(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -153,14 +154,16 @@ def it_merges_sources(config): link: scripts: - - """) + """ + ) expect(gitman.install(depth=1)) == True expect(len(os.listdir(config.location))) == 3 def it_can_handle_missing_locked_sources(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -177,7 +180,8 @@ def it_can_handle_missing_locked_sources(config): link: scripts: - - """) + """ + ) expect(gitman.install('gitman_1', depth=1)) == True @@ -195,10 +199,10 @@ def it_detects_invalid_repositories(config): shell.rm(os.path.join("deps", "gitman_1")) def describe_links(): - @pytest.fixture def config_with_link(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -207,7 +211,8 @@ def config_with_link(config): link: my_link scripts: - - """) + """ + ) return config @@ -231,10 +236,10 @@ def it_overwrites_files_with_force(config_with_link): expect(gitman.install(depth=1, force=True)) == True def describe_scripts(): - @pytest.fixture def config_with_scripts(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -244,7 +249,8 @@ def config_with_scripts(config): link: scripts: - make foobar - """) + """ + ) return config @@ -258,7 +264,8 @@ def script_failures_can_be_ignored(config_with_scripts): def describe_sparse_paths(): @pytest.fixture def config_with_scripts(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -270,7 +277,8 @@ def config_with_scripts(config): link: scripts: - - """) + """ + ) return config @@ -287,7 +295,6 @@ def it_contains_only_the_sparse_paths(config): def describe_uninstall(): - def it_deletes_dependencies_when_they_exist(config): gitman.install('gitman_1', depth=1) expect(os.path.isdir(config.location)) == True @@ -311,7 +318,6 @@ def it_deletes_the_log_file(config): def describe_keep_location(): - def it_deletes_dependencies_when_they_exist(config): gitman.install('gitman_1', depth=1) expect(os.path.isdir(config.location)) == True @@ -344,14 +350,14 @@ def it_deletes_the_log_file(config): def describe_update(): - def it_should_not_modify_config(config): gitman.update('gitman_1', depth=1) expect(config.__mapper__.text) == CONFIG def it_locks_previously_locked_dependnecies(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -382,11 +388,13 @@ def it_locks_previously_locked_dependnecies(config): link: scripts: - - """) + """ + ) gitman.update(depth=1) - expect(config.__mapper__.text) == strip(""" + expect(config.__mapper__.text) == strip( + """ location: deps sources: - name: gitman_1 @@ -417,10 +425,12 @@ def it_locks_previously_locked_dependnecies(config): link: scripts: - - """) + """ + ) def it_should_not_lock_dependnecies_when_disabled(config): - config.__mapper__.text = strip(""" + config.__mapper__.text = strip( + """ location: deps sources: - name: gitman_1 @@ -451,11 +461,13 @@ def it_should_not_lock_dependnecies_when_disabled(config): link: scripts: - - """) + """ + ) gitman.update(depth=1, lock=False) - expect(config.__mapper__.text) == strip(""" + expect(config.__mapper__.text) == strip( + """ location: deps sources: - name: gitman_1 @@ -486,12 +498,14 @@ def it_should_not_lock_dependnecies_when_disabled(config): link: scripts: - - """) + """ + ) def it_should_lock_all_dependencies_when_enabled(config): gitman.update(depth=1, lock=True) - expect(config.__mapper__.text) == CONFIG + strip(""" + expect(config.__mapper__.text) == CONFIG + strip( + """ sources_locked: - name: gitman_1 type: git @@ -520,11 +534,11 @@ def it_should_lock_all_dependencies_when_enabled(config): link: scripts: - - """) + """ + ) def describe_list(): - @freeze_time("2012-01-14 12:00:01") def it_updates_the_log(config): gitman.install() @@ -532,7 +546,8 @@ def it_updates_the_log(config): with open(config.log_path) as stream: contents = stream.read().replace(TMP, "tmp").replace('\\', '/') - expect(contents) == strip(""" + expect(contents) == strip( + """ 2012-01-14 12:00:01 tmp/deps/gitman_1: https://github.com/jacebrowning/gitman-demo @ 1de84ca1d315f81b035cd7b0ecf87ca2025cdacd tmp/deps/gitman_1/gitman_sources/gdm_3: https://github.com/jacebrowning/gdm-demo @ 050290bca3f14e13fd616604202b579853e7bfb0 @@ -541,16 +556,18 @@ def it_updates_the_log(config): tmp/deps/gitman_1/gitman_sources/gdm_4: https://github.com/jacebrowning/gdm-demo @ 63ddfd82d308ddae72d31b61cb8942c898fa05b5 tmp/deps/gitman_2: https://github.com/jacebrowning/gitman-demo @ 7bd138fe7359561a8c2ff9d195dff238794ccc04 tmp/deps/gitman_3: https://github.com/jacebrowning/gitman-demo @ 9bf18e16b956041f0267c21baad555a23237b52e - """, end='\n\n') + """, + end='\n\n', + ) def describe_lock(): - def it_records_all_versions_when_no_arguments(config): expect(gitman.update(depth=1, lock=False)) == True expect(gitman.lock()) == True - expect(config.__mapper__.text) == CONFIG + strip(""" + expect(config.__mapper__.text) == CONFIG + strip( + """ sources_locked: - name: gitman_1 type: git @@ -579,13 +596,15 @@ def it_records_all_versions_when_no_arguments(config): link: scripts: - - """) == config.__mapper__.text + """ + ) == config.__mapper__.text def it_records_specified_dependencies(config): expect(gitman.update(depth=1, lock=False)) == True expect(gitman.lock('gitman_1', 'gitman_3')) == True - expect(config.__mapper__.text) == CONFIG + strip(""" + expect(config.__mapper__.text) == CONFIG + strip( + """ sources_locked: - name: gitman_1 type: git @@ -605,7 +624,8 @@ def it_records_specified_dependencies(config): link: scripts: - - """) == config.__mapper__.text + """ + ) == config.__mapper__.text def it_should_fail_on_dirty_repositories(config): expect(gitman.update(depth=1, lock=False)) == True diff --git a/tests/test_cli.py b/tests/test_cli.py index 64c20ee4..b7efd81f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -27,7 +27,6 @@ def location(tmpdir): def describe_show(): - @patch('gitman.common.show') def it_prints_location_by_default(show, location): cli.main(['show']) @@ -38,9 +37,7 @@ def it_prints_location_by_default(show, location): def it_can_print_a_depenendcy_path(show, location): cli.main(['show', 'bar']) - expect(show.mock_calls) == [ - call(os.path.join(location, "bar"), color='path'), - ] + expect(show.mock_calls) == [call(os.path.join(location, "bar"), color='path')] def it_exits_when_no_config_found(tmpdir): tmpdir.chdir() @@ -50,7 +47,6 @@ def it_exits_when_no_config_found(tmpdir): def describe_edit(): - @patch('gitman.system.launch') def it_launches_the_config(launch, config): cli.main(['edit']) diff --git a/tests/test_main.py b/tests/test_main.py index a8624a84..67df336b 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -7,7 +7,6 @@ def describe_main(): - def it_displays_version(): code = subprocess.call([sys.executable, "-m", "gitman", "--version"]) expect(code) == 0