hookmeup

A Git hook to automate your Pipenv and Django workflow
git clone git://git.danielmoch.com/hookmeup.git
Log | Files | Refs | README | LICENSE

commit 9b1aca8c98567c17226a06d6031932245bdd2146
parent e17f7197e4c4f6df92624c63a5c01d475629b473
Author: Daniel Moch <daniel@danielmoch.com>
Date:   Sat,  1 Sep 2018 06:44:52 -0400

Expand support to all Python versions

Diffstat:
M.travis.yml | 3+++
MPipfile | 1+
MPipfile.lock | 45++++++++++++++++++++++++++++++---------------
MREADME.md | 10++++++----
Mappveyor.yml | 1+
Mpyproject.toml | 7+------
Apytest.ini | 2++
Mtests/test_hookmeup.py | 30+++++++++++++++---------------
Mtests/test_main.py | 4++--
Mtox.ini | 2+-
10 files changed, 62 insertions(+), 43 deletions(-)

diff --git a/.travis.yml b/.travis.yml @@ -24,6 +24,9 @@ jobs: include: - stage: test script: make test + python: 3.4 + - stage: test + script: make test python: 3.5 - stage: test script: make test diff --git a/Pipfile b/Pipfile @@ -13,3 +13,4 @@ pytest-mock = "*" pudb = "*" tox = "*" pylint = "*" +mock = "*" diff --git a/Pipfile.lock b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "42d3fadef08fd402d291ca260c55846114d09a8f00aca6b5728fa16ae7d00529" + "sha256": "1c061b2af98be6880907b48421b60f87f53ad3b4fca85a102fdc64115a2655fb" }, "pipfile-spec": 6, "requires": {}, @@ -90,18 +90,18 @@ }, "atomicwrites": { "hashes": [ - "sha256:6b5282987b21cd79151f51caccead7a09d0a32e89c568bd9e3c4aaa7bbdf3f3a", - "sha256:e16334d50fe0f90919ef7339c24b9b62e6abaa78cd2d226f3d94eb067eb89043" + "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", + "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" ], - "markers": "python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*'", - "version": "==1.2.0" + "markers": "python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.1.*'", + "version": "==1.2.1" }, "attrs": { "hashes": [ - "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", - "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", + "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" ], - "version": "==18.1.0" + "version": "==18.2.0" }, "coverage": { "hashes": [ @@ -190,6 +190,14 @@ ], "version": "==0.6.1" }, + "mock": { + "hashes": [ + "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", + "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" + ], + "index": "pypi", + "version": "==2.0.0" + }, "more-itertools": { "hashes": [ "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", @@ -198,6 +206,13 @@ ], "version": "==4.3.0" }, + "pbr": { + "hashes": [ + "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45", + "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa" + ], + "version": "==4.2.0" + }, "pluggy": { "hashes": [ "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", @@ -215,11 +230,11 @@ }, "py": { "hashes": [ - "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", - "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" + "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", + "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" ], - "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7'", - "version": "==1.5.4" + "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version >= '2.7'", + "version": "==1.6.0" }, "pygments": { "hashes": [ @@ -238,11 +253,11 @@ }, "pytest": { "hashes": [ - "sha256:3459a123ad5532852d36f6f4501dfe1acf4af1dd9541834a164666aa40395b02", - "sha256:96bfd45dbe863b447a3054145cd78a9d7f31475d2bce6111b133c0cc4f305118" + "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349", + "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18" ], "index": "pypi", - "version": "==3.7.2" + "version": "==3.7.4" }, "pytest-cov": { "hashes": [ diff --git a/README.md b/README.md @@ -3,19 +3,21 @@ ![GitHub](https://img.shields.io/github/license/djmoch/hookmeup.svg) [![Travis (.com)](https://img.shields.io/travis/com/djmoch/hookmeup.svg?logo=travis)](https://travis-ci.com/djmoch/hookmeup) [![AppVeyor](https://img.shields.io/appveyor/ci/djmoch/hookmeup.svg?logo=appveyor)](https://ci.appveyor.com/project/djmoch/hookmeup) -![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hookmeup.svg) [![PyPI](https://img.shields.io/pypi/v/hookmeup.svg)](https://pypi.org/project/hookmeup/) [![Coverage Status](https://coveralls.io/repos/github/djmoch/hookmeup/badge.svg?branch=master)](https://coveralls.io/github/djmoch/hookmeup?branch=master) A Git hook to automate your Pipenv and Django workflows -## Requires +## Requirements -- Python 3.5 or newer +- Any version of Python +- Python 3 is required for development due to the Flit requirement ## Features -- Fires whenever you switch branches with `git checkout` +- Fires whenever you switch branches with `git checkout`, or whenever + you run `git pull`, or basically any time Git checks files out into + your worktree - Cleans and Syncs your Pipenv if there are changes to `Pipfile` - Migrates your Django DB to it's current working state, applying and unapplying migrations as necessary diff --git a/appveyor.yml b/appveyor.yml @@ -2,6 +2,7 @@ environment: matrix: # For Python versions available on Appveyor, see # http://www.appveyor.com/docs/installed-software#python + - PYTHON: "C:\\Python34" - PYTHON: "C:\\Python35-x64" - PYTHON: "C:\\Python36" - PYTHON: "C:\\Python37" diff --git a/pyproject.toml b/pyproject.toml @@ -13,15 +13,10 @@ classifiers = ["License :: OSI Approved :: MIT License", "Environment :: Console", "Intended Audience :: Developers", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Version Control :: Git"] -requires-python=">=3.5" [tool.flit.metadata.requires-extra] -test = ['pytest', 'pytest-cov', 'pytest-mock'] -dev = ['tox', 'pylint'] +dev = ['pipenv'] [tool.flit.scripts] hookmeup = "hookmeup:main" diff --git a/pytest.ini b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +mock_use_standalone_module = true diff --git a/tests/test_hookmeup.py b/tests/test_hookmeup.py @@ -80,7 +80,7 @@ def test_install_already_installed(mock_install, mocker): ) mocker.patch('hookmeup.hookmeup.print') hookmeup.hookmeup.install({}) - assert hookmeup.hookmeup.print.call_count == 1 + hookmeup.hookmeup.print.assert_called_once() def test_error(): """Test accessing error members""" @@ -125,7 +125,7 @@ def test_post_checkout(mocker): 'new': 'HEAD' }) assert subprocess.check_output.call_count == 3 - assert hookmeup.hookmeup.adjust_pipenv.call_count == 1 + hookmeup.hookmeup.adjust_pipenv.assert_called_once() def test_post_checkout_no_changes(mocker): """Test nominal post_checkout""" @@ -183,7 +183,7 @@ def test_migrate_up(mocker): ) migrator = DjangoMigrator({'old': 'test', 'new': 'test2'}) assert migrator.migrations_changed() is True - assert subprocess.check_output.call_count == 1 + subprocess.check_output.assert_called_once() mocker.resetall() migrator.migrate() subprocess.check_output.assert_called_once_with( @@ -202,7 +202,7 @@ def test_migrate_down(mocker): ) migrator = DjangoMigrator({'old': 'test', 'new': 'test2'}) assert migrator.migrations_changed() is True - assert subprocess.check_output.call_count == 1 + subprocess.check_output.assert_called_once() mocker.resetall() migrator.migrate() assert subprocess.check_output.call_count == 2 @@ -228,7 +228,7 @@ def test_migrate_to_zero(mocker): ) migrator = DjangoMigrator({'old': 'test', 'new': 'test2'}) assert migrator.migrations_changed() is True - assert subprocess.check_output.call_count == 1 + subprocess.check_output.assert_called_once() mocker.resetall() migrator.migrate() assert subprocess.check_output.call_count == 2 @@ -254,10 +254,10 @@ def test_remove(mocker): ) mocker.patch('hookmeup.hookmeup.open', new=mock_file) hookmeup.hookmeup.remove({}) - assert subprocess.check_output.call_count == 1 - assert os.path.exists.call_count == 1 + subprocess.check_output.assert_called_once() + os.path.exists.assert_called_once() assert mock_file.call_count == 2 - assert mock_file().read.call_count == 1 + mock_file().read.assert_called_once() mock_file().writelines.assert_called_with(['#!/bin/sh\n', 'foo\n']) def test_remove_no_repo(mocker): @@ -277,7 +277,7 @@ def test_remove_no_repo(mocker): mocker.patch('hookmeup.hookmeup.open', new=mock_file) with pytest.raises(HookMeUpError): hookmeup.hookmeup.remove({}) - assert subprocess.check_output.call_count == 1 + subprocess.check_output.assert_called_once() assert os.path.exists.call_count == 0 assert mock_file.call_count == 0 assert mock_file().read.call_count == 0 @@ -299,8 +299,8 @@ def test_remove_no_hook_file(mocker): mocker.patch('hookmeup.hookmeup.open', new=mock_file) mocker.patch('hookmeup.hookmeup.print') hookmeup.hookmeup.remove({}) - assert subprocess.check_output.call_count == 1 - assert os.path.exists.call_count == 1 + subprocess.check_output.assert_called_once() + os.path.exists.assert_called_once() assert mock_file.call_count == 0 assert mock_file().read.call_count == 0 hookmeup.hookmeup.print.assert_called_with( @@ -324,10 +324,10 @@ def test_remove_not_installed(mocker): mocker.patch('hookmeup.hookmeup.open', new=mock_file) mocker.patch('hookmeup.hookmeup.print') hookmeup.hookmeup.remove({}) - assert subprocess.check_output.call_count == 1 - assert os.path.exists.call_count == 1 - assert mock_file.call_count == 1 - assert mock_file().read.call_count == 1 + subprocess.check_output.assert_called_once() + os.path.exists.assert_called_once() + mock_file.assert_called_once() + mock_file().read.assert_called_once() hookmeup.hookmeup.print.assert_called_with( 'hookmeup: hookmeup not installed. nothing to do.' ) diff --git a/tests/test_main.py b/tests/test_main.py @@ -17,7 +17,7 @@ def test_main_install(mock_hookmeup, mocker): """Test the entrypoint with the install subcommand.""" mocker.patch.object(sys, 'argv', ['hookmeup', 'install']) hookmeup.main() - assert hookmeup.hookmeup.install.call_count == 1 + hookmeup.hookmeup.install.assert_called_once() assert hookmeup.hookmeup.post_checkout.call_count == 0 def test_install_too_many_args(mock_hookmeup, mocker): @@ -91,5 +91,5 @@ def test_error(mocker): mocker.patch.object(sys, 'argv', ['hookmeup', 'install']) mocker.patch('hookmeup.print') hookmeup.main() - assert hookmeup.hookmeup.install.call_count == 1 + hookmeup.hookmeup.install.assert_called_once() hookmeup.print.called_with('hookmeup: test error') diff --git a/tox.ini b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py35, py36, py37, pylint, coverage +envlist = py34, py35, py36, py37, pylint, coverage skipsdist = True [testenv:pylint]