From ad3b17229cfffd1a71daf29ce7284bc5b547c5bc Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 7 Jan 2018 12:09:07 +0100 Subject: [PATCH 01/10] Add tox to test different python and django versions --- .travis.yml | 47 ++++++++++++++++++++++++++++++++++++++--------- README.md | 2 +- setup.py | 7 ++++++- tox.ini | 24 ++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 tox.ini diff --git a/.travis.yml b/.travis.yml index 1ddbdb7..b8ad102 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,40 @@ +sudo: false language: python -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" -script: - - flake8 django_migration_linter - - py.test + +matrix: + include: + - python: 2.7 + env: TOXENV=py27-django19 + - python: 2.7 + env: TOXENV=py27-django110 + - python: 2.7 + env: TOXENV=py27-django111 + + - python: 3.4 + env: TOXENV=py34-django19 + - python: 3.4 + env: TOXENV=py34-django110 + - python: 3.4 + env: TOXENV=py34-django111 + - python: 3.4 + env: TOXENV=py34-django20 + + - python: 3.5 + env: TOXENV=py35-django19 + - python: 3.5 + env: TOXENV=py35-django110 + - python: 3.5 + env: TOXENV=py35-django111 + - python: 3.5 + env: TOXENV=py35-django20 + + - python: 3.6 + env: TOXENV=py36-django111 + - python: 3.6 + env: TOXENV=py36-django20 + install: - - pip install -e ".[test]" + - pip install tox + +script: + - tox diff --git a/README.md b/README.md index 6c8e3b4..e807b18 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The linter will try to detect if the project is a django project and is versione ## Tests -The easiest way to run the tests is to invoke [py.test](https://docs.pytest.org/en/latest/). +The easiest way to run the tests is to invoke [tox](https://pypi.python.org/pypi/tox). ## License diff --git a/setup.py b/setup.py index 3ec8a73..8174304 100644 --- a/setup.py +++ b/setup.py @@ -26,8 +26,9 @@ install_requirements = [ ] test_requirements = [ + 'tox', 'pytest', - 'django', + 'django>=1.9', 'django-fake-database-backends', 'flake8' ] @@ -59,6 +60,10 @@ setup( 'Intended Audience :: Developers', 'Environment :: Web Environment', 'Framework :: Django', + 'Framework :: Django :: 1.9', + 'Framework :: Django :: 1.10', + 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.0', 'Programming Language :: Python', 'Programming Language :: Python :: 2', diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..694e751 --- /dev/null +++ b/tox.ini @@ -0,0 +1,24 @@ +[tox] +envlist = + py{27,34,35}-django19 + py{27,34,35}-django110 + py{27,34,35,36}-django111 + py{34,35,36}-django20 + lint + +[testenv] +commands = py.test {posargs} +extras = test +pip_pre = true +deps = + django19: django>=1.9,<1.10 + django110: django>=1.10,<1.11 + django111: django>=1.11,<2.0 + django20: django>=2.0 + +[testenv:lint] +basepython = python3.6 +deps = + flake8 +commands = + flake8 django_migration_linter From 55e1e13ad5ba79e9a8ea47908481fa7222d0c5f0 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 7 Jan 2018 12:15:23 +0100 Subject: [PATCH 02/10] Update copyright year to 2018 --- django_migration_linter/__init__.py | 2 +- django_migration_linter/migration_linter.py | 2 +- django_migration_linter/sql_analyser.py | 2 +- django_migration_linter/utils.py | 2 +- setup.py | 2 +- tests/fixtures.py | 2 +- tests/functional/test_cmd_line_call.py | 2 +- tests/functional/test_migration_linter.py | 2 +- tests/functional/test_multiple_calls.py | 2 +- tests/unit/test_linter.py | 2 +- tests/unit/test_utils.py | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/django_migration_linter/__init__.py b/django_migration_linter/__init__.py index 2ad64ea..959bac8 100644 --- a/django_migration_linter/__init__.py +++ b/django_migration_linter/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 0539f56..08f2423 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/django_migration_linter/sql_analyser.py b/django_migration_linter/sql_analyser.py index 121a767..d566072 100644 --- a/django_migration_linter/sql_analyser.py +++ b/django_migration_linter/sql_analyser.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/django_migration_linter/utils.py b/django_migration_linter/utils.py index 20def7f..b2b8f23 100644 --- a/django_migration_linter/utils.py +++ b/django_migration_linter/utils.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/setup.py b/setup.py index 8174304..8ad736d 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/fixtures.py b/tests/fixtures.py index 0bd647b..2502885 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/functional/test_cmd_line_call.py b/tests/functional/test_cmd_line_call.py index f4c5b95..f368300 100644 --- a/tests/functional/test_cmd_line_call.py +++ b/tests/functional/test_cmd_line_call.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/functional/test_migration_linter.py b/tests/functional/test_migration_linter.py index 2c78c12..17f6afc 100644 --- a/tests/functional/test_migration_linter.py +++ b/tests/functional/test_migration_linter.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/functional/test_multiple_calls.py b/tests/functional/test_multiple_calls.py index d467d19..bea9262 100644 --- a/tests/functional/test_multiple_calls.py +++ b/tests/functional/test_multiple_calls.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/test_linter.py b/tests/unit/test_linter.py index b658d93..0a4e47e 100644 --- a/tests/unit/test_linter.py +++ b/tests/unit/test_linter.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index fd6d5d0..88d20af 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -1,4 +1,4 @@ -# Copyright 2017 3YOURMIND GmbH +# Copyright 2018 3YOURMIND GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From d1d296b826794525e6b9e05b8d8c4eb0ac885081 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 7 Jan 2018 12:44:59 +0100 Subject: [PATCH 03/10] Add manifest for tox tests on travis --- .gitignore | 1 + .travis.yml | 7 +++++-- MANIFEST.in | 2 ++ setup.py | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 MANIFEST.in diff --git a/.gitignore b/.gitignore index 6060cf3..1a58382 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ dist/ .cache/ env/ tests/test_project_fixtures/*/.git/ +.tox/ diff --git a/.travis.yml b/.travis.yml index b8ad102..b13ad77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ sudo: false language: python matrix: - include: + include: - python: 2.7 env: TOXENV=py27-django19 - python: 2.7 @@ -33,8 +33,11 @@ matrix: - python: 3.6 env: TOXENV=py36-django20 + - python: 3.6 + env: TOXENV=lint + install: - pip install tox script: - - tox + - tox diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..04f196a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include README.md +include LICENSE diff --git a/setup.py b/setup.py index 8ad736d..50dc877 100644 --- a/setup.py +++ b/setup.py @@ -26,8 +26,8 @@ install_requirements = [ ] test_requirements = [ - 'tox', 'pytest', + 'tox', 'django>=1.9', 'django-fake-database-backends', 'flake8' From 8adffed958983eb5bee89c815bbb02272d0f6b1b Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 7 Jan 2018 17:34:08 +0100 Subject: [PATCH 04/10] Call venv linter in tests --- setup.py | 1 - tests/functional/test_cmd_line_call.py | 27 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 50dc877..a1a1b35 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,6 @@ test_requirements = [ 'tox', 'django>=1.9', 'django-fake-database-backends', - 'flake8' ] setup( diff --git a/tests/functional/test_cmd_line_call.py b/tests/functional/test_cmd_line_call.py index f368300..bc34b15 100644 --- a/tests/functional/test_cmd_line_call.py +++ b/tests/functional/test_cmd_line_call.py @@ -16,11 +16,18 @@ import unittest from subprocess import Popen, PIPE from django_migration_linter import utils from tests import fixtures +import sys class CallLinterFromCommandLineTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + super(CallLinterFromCommandLineTest, cls).setUpClass() + linter_name = 'django-migration-linter' + cls.linter_exec = '{0}/bin/{1}'.format(sys.prefix, linter_name) if hasattr(sys, 'real_prefix') else linter_name + def test_call_linter_cmd_line_working(self): - cmd = 'django-migration-linter {0}'.format(fixtures.CORRECT_PROJECT) + cmd = '{0} {1}'.format(self.linter_exec, fixtures.CORRECT_PROJECT) process = Popen( cmd, shell=True, stdout=PIPE, stderr=PIPE) @@ -33,7 +40,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('OK')) def test_call_linter_cmd_line_errors(self): - cmd = 'django-migration-linter {0}'.format( + cmd = '{0} {1}'.format( + self.linter_exec, fixtures.ADD_NOT_NULL_COLUMN_PROJECT) process = Popen( @@ -48,7 +56,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue('RENAMING tables' in lines[2]) def test_call_linter_cmd_line_exclude_apps(self): - cmd = 'django-migration-linter {0} --exclude-apps test_app2'.format( + cmd = '{0} {1} --exclude-apps test_app2'.format( + self.linter_exec, fixtures.CORRECT_PROJECT) process = Popen( @@ -62,7 +71,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('IGNORE')) def test_call_linter_cmd_line_include_apps(self): - cmd = 'django-migration-linter {0} --include-apps test_app2'.format( + cmd = '{0} {1} --include-apps test_app2'.format( + self.linter_exec, fixtures.CORRECT_PROJECT) process = Popen( @@ -76,7 +86,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('OK')) def test_call_linter_cmd_line_ignore_name(self): - cmd = 'django-migration-linter {0} --ignore-name 0001_initial'.format( + cmd = '{0} {1} --ignore-name 0001_initial'.format( + self.linter_exec, fixtures.CORRECT_PROJECT) process = Popen( @@ -90,7 +101,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('OK')) def test_call_linter_cmd_line_ignore_name_contains(self): - cmd = 'django-migration-linter {0} --ignore-name-contains 0001'.format( + cmd = '{0} {1} --ignore-name-contains 0001'.format( + self.linter_exec, fixtures.CORRECT_PROJECT) process = Popen( @@ -104,7 +116,8 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('IGNORE')) def test_call_linter_cmd_line_git_id(self): - cmd = 'django-migration-linter {0} d7125d5f4f0cc9623f670a66c54f131acc50032d'.format( + cmd = '{0} {1} d7125d5f4f0cc9623f670a66c54f131acc50032d'.format( + self.linter_exec, fixtures.MULTI_COMMIT_PROJECT) fixtures.prepare_git_project(fixtures.MULTI_COMMIT_PROJECT) From d6c8793d605471d1187a8a12bfd220f8839681cb Mon Sep 17 00:00:00 2001 From: Felix Bauer Date: Thu, 11 Jan 2018 15:04:02 +0100 Subject: [PATCH 05/10] Use pypandoc to convert markdown to pypi friendly format See https://pypi.python.org/pypi/django-migration-linter And then see https://stackoverflow.com/questions/26737222/pypi-description-markdown-doesnt-work --- setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 3ec8a73..3a7e1c8 100644 --- a/setup.py +++ b/setup.py @@ -19,8 +19,11 @@ from setuptools import setup, find_packages PROJECT_DIR = path.abspath(path.dirname(__file__)) -with open(path.join(PROJECT_DIR, 'README.md'), encoding='utf-8') as f: - long_description = f.read() +try: + import pypandoc + long_description = pypandoc.convert('README.md', 'rst') +except(IOError, ImportError): + long_description = open('README.md').read() install_requirements = [ ] From d5c659db860b8a3d09b286d3dfd9ccf427bab660 Mon Sep 17 00:00:00 2001 From: Felix Bauer Date: Thu, 11 Jan 2018 16:06:50 +0100 Subject: [PATCH 06/10] Improve error output --- django_migration_linter/migration_linter.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 0539f56..050589f 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -18,8 +18,8 @@ import os import re from subprocess import Popen, PIPE import sys -from . import utils -from .sql_analyser import analyse_sql_statements +import utils +from sql_analyser import analyse_sql_statements class MigrationLinter(object): @@ -139,7 +139,10 @@ class MigrationLinter(object): sql_statements.append(line) sqlmigrate_process.wait() if sqlmigrate_process.returncode != 0: - raise RuntimeError('sqlmigrate command failed') + out, err = sqlmigrate_process.communicate() + print('sqlmigrate command failed') + print(err.decode('ascii')) + raise RuntimeError() log.info('Found {0} sql migration lines'.format(len(sql_statements))) return sql_statements From dcbcb0883cbe2020366140537e20a99726fbb383 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Fri, 12 Jan 2018 23:01:11 +0100 Subject: [PATCH 07/10] Use python exe in current venv --- django_migration_linter/migration_linter.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 08f2423..4ef197e 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -43,6 +43,7 @@ class MigrationLinter(object): self.include_apps = kwargs.get('include_apps', None) self.exclude_apps = kwargs.get('exclude_apps', None) self.database = kwargs.get('database', None) or 'default' + self.python_exe = '{0}/bin/{1}'.format(sys.prefix, 'python') if hasattr(sys, 'real_prefix') else 'python' # Initialise counters self.nb_valid = 0 @@ -125,9 +126,11 @@ class MigrationLinter(object): """ git_diff_command = ( 'cd {0} && ' - 'python manage.py sqlmigrate {1} {2} ' - '--database {3}').format( - self.django_path, app_name, migration_name, self.database) + '{1} manage.py sqlmigrate {2} {3} ' + '--database {4}').format( + self.django_path, + self.python_exe, app_name, migration_name, + self.database) log.info('Executing {0}'.format(git_diff_command)) sqlmigrate_process = Popen( git_diff_command, shell=True, stdout=PIPE, stderr=PIPE) From 317156bf2b9873348a09ebf72d21611e09d1b83f Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Fri, 12 Jan 2018 23:23:11 +0100 Subject: [PATCH 08/10] Remove django 1.9 support and fix PEP8 --- .travis.yml | 6 ------ django_migration_linter/migration_linter.py | 3 ++- setup.py | 3 +-- tox.ini | 2 -- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index b13ad77..5fea858 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,15 +3,11 @@ language: python matrix: include: - - python: 2.7 - env: TOXENV=py27-django19 - python: 2.7 env: TOXENV=py27-django110 - python: 2.7 env: TOXENV=py27-django111 - - python: 3.4 - env: TOXENV=py34-django19 - python: 3.4 env: TOXENV=py34-django110 - python: 3.4 @@ -19,8 +15,6 @@ matrix: - python: 3.4 env: TOXENV=py34-django20 - - python: 3.5 - env: TOXENV=py35-django19 - python: 3.5 env: TOXENV=py35-django110 - python: 3.5 diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 4ef197e..edc32ff 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -43,7 +43,8 @@ class MigrationLinter(object): self.include_apps = kwargs.get('include_apps', None) self.exclude_apps = kwargs.get('exclude_apps', None) self.database = kwargs.get('database', None) or 'default' - self.python_exe = '{0}/bin/{1}'.format(sys.prefix, 'python') if hasattr(sys, 'real_prefix') else 'python' + self.python_exe = '{0}/bin/{1}'.format(sys.prefix, 'python') if \ + hasattr(sys, 'real_prefix') else 'python' # Initialise counters self.nb_valid = 0 diff --git a/setup.py b/setup.py index a1a1b35..9f53385 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ install_requirements = [ test_requirements = [ 'pytest', 'tox', - 'django>=1.9', + 'django>=1.10', 'django-fake-database-backends', ] @@ -59,7 +59,6 @@ setup( 'Intended Audience :: Developers', 'Environment :: Web Environment', 'Framework :: Django', - 'Framework :: Django :: 1.9', 'Framework :: Django :: 1.10', 'Framework :: Django :: 1.11', 'Framework :: Django :: 2.0', diff --git a/tox.ini b/tox.ini index 694e751..ac72378 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ [tox] envlist = - py{27,34,35}-django19 py{27,34,35}-django110 py{27,34,35,36}-django111 py{34,35,36}-django20 @@ -11,7 +10,6 @@ commands = py.test {posargs} extras = test pip_pre = true deps = - django19: django>=1.9,<1.10 django110: django>=1.10,<1.11 django111: django>=1.11,<2.0 django20: django>=2.0 From 306551234aea53c3c2d4cd185f869880aa93e246 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 13 Jan 2018 00:31:24 +0100 Subject: [PATCH 09/10] Fix import errors for python3 & print error message on stderr (through exception message) --- django_migration_linter/migration_linter.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 1864f02..69158ff 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -18,8 +18,8 @@ import os import re from subprocess import Popen, PIPE import sys -import utils -from sql_analyser import analyse_sql_statements +from . import utils +from .sql_analyser import analyse_sql_statements class MigrationLinter(object): @@ -143,10 +143,9 @@ class MigrationLinter(object): sql_statements.append(line) sqlmigrate_process.wait() if sqlmigrate_process.returncode != 0: - out, err = sqlmigrate_process.communicate() - print('sqlmigrate command failed') - print(err.decode('ascii')) - raise RuntimeError() + _, err = sqlmigrate_process.communicate() + raise RuntimeError('sqlmigrate command failed {0}'.format( + err.decode('utf-8'))) log.info('Found {0} sql migration lines'.format(len(sql_statements))) return sql_statements From b24315c1d9238e10587ec4a27e839384c0450c82 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 13 Jan 2018 00:43:53 +0100 Subject: [PATCH 10/10] Add contributing section to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e807b18..d41e828 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,11 @@ The linter will try to detect if the project is a django project and is versione The easiest way to run the tests is to invoke [tox](https://pypi.python.org/pypi/tox). +## Contributing + +First, thank you very much if you want to contribute to the project. +Please base your work on the `dev` branch and also target this branch in your pull request. + ## License *django-migration-linter* is released under the [Apache 2.0 License](./LICENSE).