From fa083d0b8f2a832e2886e6812751bc94415b4e1f Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Thu, 18 Jan 2018 11:53:55 +0200 Subject: [PATCH 01/26] Update test matrix and how tests are started on Travis --- .travis.yml | 21 ++++++++++++--------- scripts/travis-build.sh | 9 --------- scripts/travis-install.sh | 12 ------------ scripts/travis_skip.py | 8 -------- 4 files changed, 12 insertions(+), 38 deletions(-) delete mode 100755 scripts/travis-build.sh delete mode 100755 scripts/travis-install.sh delete mode 100755 scripts/travis_skip.py diff --git a/.travis.yml b/.travis.yml index a26e70ca..8a1983d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,21 @@ sudo: false language: python python: - - "2.7" - - "3.3" - - "3.4" - "3.5" + - "3.6" env: - - DJANGO='Django>=1.7,<1.8' SKIP='2.6 3.5' - - DJANGO='Django>=1.8,<1.9' SKIP='2.6' - - DJANGO='Django>=1.9,<1.10' SKIP='2.6 3.3' - - DJANGO='Django>=1.10,<1.11' SKIP='2.6 3.3' + - DJANGO="1.11,<2.0" + - DJANGO="2.0,<3.0" +matrix: + include: + - python: 2.7 + env: DJANGO="1.11,<2.0" + install: - scripts/travis-install.sh + - pip install coverage coveralls + - pip install "Django>=$DJANGO" + - pip install git+https://github.com/landscapeio/pylint-plugin-utils.git@master script: - scripts/travis-build.sh + - PYTHONPATH=. coverage run test/test_func.py after_success: coveralls diff --git a/scripts/travis-build.sh b/scripts/travis-build.sh deleted file mode 100755 index 02251cae..00000000 --- a/scripts/travis-build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -python scripts/travis_skip.py - -if [ "$?" -eq "0" ] -then - coverage run test/test_func.py -else - echo "Skipping" -fi diff --git a/scripts/travis-install.sh b/scripts/travis-install.sh deleted file mode 100755 index a977c103..00000000 --- a/scripts/travis-install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -python scripts/travis_skip.py - -if [ "$?" -eq "0" ] -then - pip install coverage coveralls - pip install $DJANGO - pip install git+https://github.com/landscapeio/pylint-plugin-utils.git@develop - pip install --editable . -else - echo "Skipping" -fi diff --git a/scripts/travis_skip.py b/scripts/travis_skip.py deleted file mode 100755 index 8b0932b3..00000000 --- a/scripts/travis_skip.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python -import os -import sys -for skip_ver in os.environ.get('SKIP', '').split(): - skip_ver = tuple(map(int, skip_ver.split('.'))) - if skip_ver == sys.version_info[:len(skip_ver)]: - sys.exit(1) -sys.exit(0) From 533b66c8262c31635e3e9e64b05c1a598bb25493 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 14:39:39 +0200 Subject: [PATCH 02/26] Update the way we load tests this mimics more closely what pylint does for their own tests and doesn't rely on deprecated functionality. Fixes https://github.com/landscapeio/pylint-django/issues/107 and https://github.com/landscapeio/pylint-django/issues/97 Obsoletes https://github.com/landscapeio/pylint-django/pull/98 --- test/test_func.py | 86 +++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 56 deletions(-) diff --git a/test/test_func.py b/test/test_func.py index 473ba949..b6fd2745 100644 --- a/test/test_func.py +++ b/test/test_func.py @@ -1,73 +1,47 @@ import os import sys -import unittest -from django.conf import settings -from pylint.testutils import make_tests, LintTestUsingFile, cb_test_gen, linter -from pylint_django.compat import django_version - - -settings.configure() - - -HERE = os.path.dirname(os.path.abspath(__file__)) +import pytest +import pylint +# because there's no __init__ file in pylint/test/ +sys.path.append(os.path.join(os.path.dirname(pylint.__file__), 'test')) +import test_functional -linter.load_plugin_modules(['pylint_django']) -# Disable some things on Python2.6, since we use a different pylint version here -# (1.3 on Python2.6, 1.4+ on later versions) -if sys.version_info < (2, 7): - linter.global_set_option('required-attributes', ()) - linter.global_set_option('disable', ('E0012',)) - - -SKIP_TESTS_FOR_DJANGO_VERSION = { - # if the second value is False, skip the test, otherwise run it - ('func_noerror_protected_meta_access', django_version >= (1, 8)), -} - +from pylint_django.compat import django_version -def module_exists(module_name): - try: - __import__(module_name) - except ImportError: - return False - else: - return True +class PylintDjangoLintModuleTest(test_functional.LintModuleTest): + """ + Only used so that we can load this plugin into the linter! + """ + def __init__(self, test_file): + super(PylintDjangoLintModuleTest, self).__init__(test_file) + self._linter.load_plugin_modules(['pylint_django']) -def tests(input_dir, messages_dir): - callbacks = [cb_test_gen(LintTestUsingFile)] - input_dir = os.path.join(HERE, input_dir) - messages_dir = os.path.join(HERE, messages_dir) +def get_tests(): + HERE = os.path.dirname(os.path.abspath(__file__)) + input_dir = os.path.join(HERE, 'input') - # first tests which pass for all Django versions - tests = make_tests(input_dir, messages_dir, None, callbacks) + suite = [] + for fname in os.listdir(input_dir): + if fname != '__init__.py' and fname.endswith('.py'): + suite.append(test_functional.FunctionalTestFile(input_dir, fname)) + return suite - # now skip some tests test for specific versions - for example, - # _meta access should not work for django<1.8 but should run and - # pass for django 1.4 - skip the tests which will be checking - # a piece of functionality in pylint-django that should only - # in higher versions. - specific_tests = [] - for test_name, version_range in SKIP_TESTS_FOR_DJANGO_VERSION: - if not version_range: - specific_tests.append(test_name) - filter_rgx = '(%s)' % '|'.join(specific_tests) - tests += make_tests(os.path.join(input_dir, 'versions'), messages_dir, filter_rgx, callbacks) - return tests +TESTS = get_tests() +TESTS_NAMES = [t.base for t in TESTS] -def suite(): - test_list = tests('input', 'messages') - - if module_exists('rest_framework'): - test_list += tests('external_drf', '') +@pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES) +def test_everything(test_file): + # copied from pylint.tests.test_functional.test_functional + LintTest = PylintDjangoLintModuleTest(test_file) + LintTest.setUp() + LintTest._runTest() - return unittest.TestSuite([unittest.makeSuite(test, suiteClass=unittest.TestSuite) - for test in test_list]) if __name__ == '__main__': - unittest.main(defaultTest='suite') + sys.exit(pytest.main(sys.argv)) From fbdddd642289f25bdda44607763a7d3e82f2a812 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 14:50:35 +0200 Subject: [PATCH 03/26] Remove missing W5101 and W5103 pylint warnings --- test/input/func_noerror_classviews.py | 2 +- test/input/func_noerror_foreign_key_attributes.py | 2 +- test/input/func_noerror_foreign_key_ids.py | 2 +- test/input/func_noerror_foreign_key_sets.py | 2 +- test/input/func_noerror_foreignkeys.py | 2 +- test/input/func_noerror_forms_py33.py | 2 +- test/input/func_noerror_forms_py_28.py | 2 +- test/input/func_noerror_formview_ancestors.py | 2 +- test/input/func_noerror_ignore_meta_subclass.py | 2 +- test/input/func_noerror_issue_46.py | 2 +- test/input/func_noerror_manytomanyfield.py | 2 +- test/input/func_noerror_model_fields.py | 2 +- test/input/func_noerror_model_methods.py | 2 +- test/input/func_noerror_models_py33.py | 2 +- test/input/func_noerror_models_py_28.py | 2 +- test/input/versions/func_noerror_proteted_meta_access.py | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/input/func_noerror_classviews.py b/test/input/func_noerror_classviews.py index 249e86d5..4683cf11 100644 --- a/test/input/func_noerror_classviews.py +++ b/test/input/func_noerror_classviews.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about attributes and methods when using Class-based Views """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.views.generic import TemplateView diff --git a/test/input/func_noerror_foreign_key_attributes.py b/test/input/func_noerror_foreign_key_attributes.py index b0b55a9e..272747dc 100644 --- a/test/input/func_noerror_foreign_key_attributes.py +++ b/test/input/func_noerror_foreign_key_attributes.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key sets on models """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_foreign_key_ids.py b/test/input/func_noerror_foreign_key_ids.py index 201403b9..f38e5b9f 100644 --- a/test/input/func_noerror_foreign_key_ids.py +++ b/test/input/func_noerror_foreign_key_ids.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key id access """ -# pylint: disable=C0111,W5101,wrong-import-position +# pylint: disable=C0111,wrong-import-position from django.db import models diff --git a/test/input/func_noerror_foreign_key_sets.py b/test/input/func_noerror_foreign_key_sets.py index 779adf4b..d96c50eb 100644 --- a/test/input/func_noerror_foreign_key_sets.py +++ b/test/input/func_noerror_foreign_key_sets.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key sets on models """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_foreignkeys.py b/test/input/func_noerror_foreignkeys.py index fa82df5a..fc6f3e91 100644 --- a/test/input/func_noerror_foreignkeys.py +++ b/test/input/func_noerror_foreignkeys.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on Django model fields. """ -# pylint: disable=C0111,W5101,wrong-import-position +# pylint: disable=C0111,wrong-import-position from django.db import models from django.db.models import ForeignKey, OneToOneField diff --git a/test/input/func_noerror_forms_py33.py b/test/input/func_noerror_forms_py33.py index 05206680..4cee2a49 100644 --- a/test/input/func_noerror_forms_py33.py +++ b/test/input/func_noerror_forms_py33.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=C0111,W5101,R0903,wrong-import-position +# pylint: disable=C0111,R0903,wrong-import-position from django import forms diff --git a/test/input/func_noerror_forms_py_28.py b/test/input/func_noerror_forms_py_28.py index b972f523..a23c66e0 100644 --- a/test/input/func_noerror_forms_py_28.py +++ b/test/input/func_noerror_forms_py_28.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=C0111,W5101,R0903 +# pylint: disable=C0111,R0903 from django import forms diff --git a/test/input/func_noerror_formview_ancestors.py b/test/input/func_noerror_formview_ancestors.py index 18f9d3be..fd1fba1d 100644 --- a/test/input/func_noerror_formview_ancestors.py +++ b/test/input/func_noerror_formview_ancestors.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about django FormViews having too many ancestors """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.views.generic import FormView diff --git a/test/input/func_noerror_ignore_meta_subclass.py b/test/input/func_noerror_ignore_meta_subclass.py index 7e612619..fc4b3d49 100644 --- a/test/input/func_noerror_ignore_meta_subclass.py +++ b/test/input/func_noerror_ignore_meta_subclass.py @@ -2,7 +2,7 @@ This test ensures that a 'Meta' class defined on a Django model does not raise warnings such as 'old-style-class' and 'too-few-public-methods' """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_issue_46.py b/test/input/func_noerror_issue_46.py index 1adb5974..1164094f 100644 --- a/test/input/func_noerror_issue_46.py +++ b/test/input/func_noerror_issue_46.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about raising DoesNotExist """ -# pylint: disable=C0111,W5101,W5103 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_manytomanyfield.py b/test/input/func_noerror_manytomanyfield.py index e98c2cc9..b052e97d 100644 --- a/test/input/func_noerror_manytomanyfield.py +++ b/test/input/func_noerror_manytomanyfield.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on many-to-many relationships """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_model_fields.py b/test/input/func_noerror_model_fields.py index 7009814e..330bc851 100644 --- a/test/input/func_noerror_model_fields.py +++ b/test/input/func_noerror_model_fields.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on Django model fields. """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from __future__ import print_function from datetime import datetime, date from decimal import Decimal diff --git a/test/input/func_noerror_model_methods.py b/test/input/func_noerror_model_methods.py index 43a27744..7a2b70f0 100644 --- a/test/input/func_noerror_model_methods.py +++ b/test/input/func_noerror_model_methods.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about using Model and Manager methods """ -# pylint: disable=C0111,W5101,W5103 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_models_py33.py b/test/input/func_noerror_models_py33.py index 871ff471..f7fc7e4a 100644 --- a/test/input/func_noerror_models_py33.py +++ b/test/input/func_noerror_models_py33.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about a fairly standard Django Model """ -# pylint: disable=C0111,W5101 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/func_noerror_models_py_28.py b/test/input/func_noerror_models_py_28.py index 175c3dbf..1ad0f989 100644 --- a/test/input/func_noerror_models_py_28.py +++ b/test/input/func_noerror_models_py_28.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about a fairly standard Django Model """ -# pylint: disable=C0111,W5101,W5103 +# pylint: disable=C0111 from django.db import models diff --git a/test/input/versions/func_noerror_proteted_meta_access.py b/test/input/versions/func_noerror_proteted_meta_access.py index 762dc8f7..f48a7a7d 100644 --- a/test/input/versions/func_noerror_proteted_meta_access.py +++ b/test/input/versions/func_noerror_proteted_meta_access.py @@ -5,7 +5,7 @@ (see https://github.com/landscapeio/pylint-django/issues/66, and https://docs.djangoproject.com/en/1.9/ref/models/meta/) """ -# pylint: disable=C0111,W5101,W5103 +# pylint: disable=C0111 from __future__ import print_function from django.db import models From d8a55c3e5f328f7718377c9e706774aec91e406c Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 14:52:16 +0200 Subject: [PATCH 04/26] Replace C0111 with missing-docstring for better readability --- test/input/func_model_does_not_use_unicode_py33.py | 2 +- test/input/func_model_requires_unicode_py_28.py | 2 +- test/input/func_model_unicode_parent_py_28.py | 2 +- test/input/func_noerror_classviews.py | 2 +- test/input/func_noerror_foreign_key_attributes.py | 2 +- test/input/func_noerror_foreign_key_ids.py | 2 +- test/input/func_noerror_foreign_key_sets.py | 2 +- test/input/func_noerror_foreignkeys.py | 2 +- test/input/func_noerror_form_fields.py | 2 +- test/input/func_noerror_forms_py33.py | 2 +- test/input/func_noerror_forms_py_28.py | 2 +- test/input/func_noerror_formview_ancestors.py | 2 +- test/input/func_noerror_ignore_meta_subclass.py | 2 +- test/input/func_noerror_issue_46.py | 2 +- test/input/func_noerror_manytomanyfield.py | 2 +- test/input/func_noerror_model_fields.py | 2 +- test/input/func_noerror_model_methods.py | 2 +- test/input/func_noerror_model_unicode_callable.py | 2 +- test/input/func_noerror_model_unicode_lambda.py | 2 +- test/input/func_noerror_models_py33.py | 2 +- test/input/func_noerror_models_py_28.py | 2 +- test/input/func_noerror_unicode_py2_compatible.py | 2 +- test/input/func_noerror_urls.py | 2 +- test/input/versions/func_noerror_proteted_meta_access.py | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/input/func_model_does_not_use_unicode_py33.py b/test/input/func_model_does_not_use_unicode_py33.py index 34258e1c..459082b7 100644 --- a/test/input/func_model_does_not_use_unicode_py33.py +++ b/test/input/func_model_does_not_use_unicode_py33.py @@ -1,7 +1,7 @@ """ Ensures that django models without a __unicode__ method are flagged """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_model_requires_unicode_py_28.py b/test/input/func_model_requires_unicode_py_28.py index 72cc761f..45322112 100644 --- a/test/input/func_model_requires_unicode_py_28.py +++ b/test/input/func_model_requires_unicode_py_28.py @@ -2,7 +2,7 @@ Ensures that django models without a __unicode__ method are flagged, but only models which are not abstract """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_model_unicode_parent_py_28.py b/test/input/func_model_unicode_parent_py_28.py index 38e937a1..42844038 100644 --- a/test/input/func_model_unicode_parent_py_28.py +++ b/test/input/func_model_unicode_parent_py_28.py @@ -2,7 +2,7 @@ Ensures that django models whose parent have a __unicide__ method are not flagged """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_classviews.py b/test/input/func_noerror_classviews.py index 4683cf11..b37b101d 100644 --- a/test/input/func_noerror_classviews.py +++ b/test/input/func_noerror_classviews.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about attributes and methods when using Class-based Views """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.views.generic import TemplateView diff --git a/test/input/func_noerror_foreign_key_attributes.py b/test/input/func_noerror_foreign_key_attributes.py index 272747dc..3283e92d 100644 --- a/test/input/func_noerror_foreign_key_attributes.py +++ b/test/input/func_noerror_foreign_key_attributes.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key sets on models """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_foreign_key_ids.py b/test/input/func_noerror_foreign_key_ids.py index f38e5b9f..8afcf73f 100644 --- a/test/input/func_noerror_foreign_key_ids.py +++ b/test/input/func_noerror_foreign_key_ids.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key id access """ -# pylint: disable=C0111,wrong-import-position +# pylint: disable=missing-docstring,wrong-import-position from django.db import models diff --git a/test/input/func_noerror_foreign_key_sets.py b/test/input/func_noerror_foreign_key_sets.py index d96c50eb..b68eccaf 100644 --- a/test/input/func_noerror_foreign_key_sets.py +++ b/test/input/func_noerror_foreign_key_sets.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about foreign key sets on models """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_foreignkeys.py b/test/input/func_noerror_foreignkeys.py index fc6f3e91..296076a9 100644 --- a/test/input/func_noerror_foreignkeys.py +++ b/test/input/func_noerror_foreignkeys.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on Django model fields. """ -# pylint: disable=C0111,wrong-import-position +# pylint: disable=missing-docstring,wrong-import-position from django.db import models from django.db.models import ForeignKey, OneToOneField diff --git a/test/input/func_noerror_form_fields.py b/test/input/func_noerror_form_fields.py index 683fc78e..28ceace6 100644 --- a/test/input/func_noerror_form_fields.py +++ b/test/input/func_noerror_form_fields.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on Django form forms. """ -# pylint: disable=C0111,R0904 +# pylint: disable=missing-docstring,R0904 from __future__ import print_function from datetime import datetime, date from django import forms diff --git a/test/input/func_noerror_forms_py33.py b/test/input/func_noerror_forms_py33.py index 4cee2a49..abc87c00 100644 --- a/test/input/func_noerror_forms_py33.py +++ b/test/input/func_noerror_forms_py33.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=C0111,R0903,wrong-import-position +# pylint: disable=missing-docstring,R0903,wrong-import-position from django import forms diff --git a/test/input/func_noerror_forms_py_28.py b/test/input/func_noerror_forms_py_28.py index a23c66e0..7dbf25d4 100644 --- a/test/input/func_noerror_forms_py_28.py +++ b/test/input/func_noerror_forms_py_28.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=C0111,R0903 +# pylint: disable=missing-docstring,R0903 from django import forms diff --git a/test/input/func_noerror_formview_ancestors.py b/test/input/func_noerror_formview_ancestors.py index fd1fba1d..35f72c9c 100644 --- a/test/input/func_noerror_formview_ancestors.py +++ b/test/input/func_noerror_formview_ancestors.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about django FormViews having too many ancestors """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.views.generic import FormView diff --git a/test/input/func_noerror_ignore_meta_subclass.py b/test/input/func_noerror_ignore_meta_subclass.py index fc4b3d49..af1c9b08 100644 --- a/test/input/func_noerror_ignore_meta_subclass.py +++ b/test/input/func_noerror_ignore_meta_subclass.py @@ -2,7 +2,7 @@ This test ensures that a 'Meta' class defined on a Django model does not raise warnings such as 'old-style-class' and 'too-few-public-methods' """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_issue_46.py b/test/input/func_noerror_issue_46.py index 1164094f..0e20d95e 100644 --- a/test/input/func_noerror_issue_46.py +++ b/test/input/func_noerror_issue_46.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about raising DoesNotExist """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_manytomanyfield.py b/test/input/func_noerror_manytomanyfield.py index b052e97d..8ff877ca 100644 --- a/test/input/func_noerror_manytomanyfield.py +++ b/test/input/func_noerror_manytomanyfield.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on many-to-many relationships """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_model_fields.py b/test/input/func_noerror_model_fields.py index 330bc851..d30bb1cd 100644 --- a/test/input/func_noerror_model_fields.py +++ b/test/input/func_noerror_model_fields.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about various methods on Django model fields. """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from __future__ import print_function from datetime import datetime, date from decimal import Decimal diff --git a/test/input/func_noerror_model_methods.py b/test/input/func_noerror_model_methods.py index 7a2b70f0..0cad4ec2 100644 --- a/test/input/func_noerror_model_methods.py +++ b/test/input/func_noerror_model_methods.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about using Model and Manager methods """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_model_unicode_callable.py b/test/input/func_noerror_model_unicode_callable.py index 0ef1406c..a963ee0e 100644 --- a/test/input/func_noerror_model_unicode_callable.py +++ b/test/input/func_noerror_model_unicode_callable.py @@ -1,7 +1,7 @@ """ Ensures that django models without a __unicode__ method are flagged """ -# pylint: disable=C0111,wrong-import-position +# pylint: disable=missing-docstring,wrong-import-position from django.db import models diff --git a/test/input/func_noerror_model_unicode_lambda.py b/test/input/func_noerror_model_unicode_lambda.py index 22ad0e7a..25c2ff11 100644 --- a/test/input/func_noerror_model_unicode_lambda.py +++ b/test/input/func_noerror_model_unicode_lambda.py @@ -1,7 +1,7 @@ """ Ensures that django models without a __unicode__ method are flagged """ -# pylint: disable=C0111,wrong-import-position +# pylint: disable=missing-docstring,wrong-import-position from django.db import models diff --git a/test/input/func_noerror_models_py33.py b/test/input/func_noerror_models_py33.py index f7fc7e4a..7ad22bbe 100644 --- a/test/input/func_noerror_models_py33.py +++ b/test/input/func_noerror_models_py33.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about a fairly standard Django Model """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_models_py_28.py b/test/input/func_noerror_models_py_28.py index 1ad0f989..c5405906 100644 --- a/test/input/func_noerror_models_py_28.py +++ b/test/input/func_noerror_models_py_28.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about a fairly standard Django Model """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.db import models diff --git a/test/input/func_noerror_unicode_py2_compatible.py b/test/input/func_noerror_unicode_py2_compatible.py index 454039a5..840a812a 100644 --- a/test/input/func_noerror_unicode_py2_compatible.py +++ b/test/input/func_noerror_unicode_py2_compatible.py @@ -4,7 +4,7 @@ See https://github.com/landscapeio/pylint-django/issues/10 """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from django.utils.encoding import python_2_unicode_compatible from django.db import models diff --git a/test/input/func_noerror_urls.py b/test/input/func_noerror_urls.py index b41ad0ad..3d04dd15 100644 --- a/test/input/func_noerror_urls.py +++ b/test/input/func_noerror_urls.py @@ -2,7 +2,7 @@ Checks that Pylint does not complain about attributes and methods when creating a typical urls.py """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring # pylint: disable=C0103 # ^ eventually we should be able to override or update the # CONST_NAME_RGX value diff --git a/test/input/versions/func_noerror_proteted_meta_access.py b/test/input/versions/func_noerror_proteted_meta_access.py index f48a7a7d..c8ec668d 100644 --- a/test/input/versions/func_noerror_proteted_meta_access.py +++ b/test/input/versions/func_noerror_proteted_meta_access.py @@ -5,7 +5,7 @@ (see https://github.com/landscapeio/pylint-django/issues/66, and https://docs.djangoproject.com/en/1.9/ref/models/meta/) """ -# pylint: disable=C0111 +# pylint: disable=missing-docstring from __future__ import print_function from django.db import models From 59257f9cf9507d73fe9e73d4a0e31c7733705c4d Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 15:04:51 +0200 Subject: [PATCH 05/26] Add required on_delete attribute, fixes no-value-for-parameter since we're testing with latest Django versions this is now required for all ForeignKey fields --- test/input/func_noerror_foreign_key_attributes.py | 4 ++-- test/input/func_noerror_foreign_key_ids.py | 2 +- test/input/func_noerror_foreign_key_sets.py | 5 +++-- test/input/func_noerror_foreignkeys.py | 8 ++++---- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/input/func_noerror_foreign_key_attributes.py b/test/input/func_noerror_foreign_key_attributes.py index 3283e92d..1ae57677 100644 --- a/test/input/func_noerror_foreign_key_attributes.py +++ b/test/input/func_noerror_foreign_key_attributes.py @@ -12,8 +12,8 @@ class SomeModel(models.Model): class OtherModel(models.Model): - something = models.ForeignKey(SomeModel) - elsething = models.OneToOneField(SomeModel) + something = models.ForeignKey(SomeModel, on_delete=models.CASCADE) + elsething = models.OneToOneField(SomeModel, on_delete=models.CASCADE) def something_doer(self): part_a = '%s - %s' % (self.something.name, self.something.timestamp) diff --git a/test/input/func_noerror_foreign_key_ids.py b/test/input/func_noerror_foreign_key_ids.py index 8afcf73f..90370735 100644 --- a/test/input/func_noerror_foreign_key_ids.py +++ b/test/input/func_noerror_foreign_key_ids.py @@ -10,7 +10,7 @@ class SomeModel(models.Model): class SomeOtherModel(models.Model): - some_model = models.ForeignKey(SomeModel) + some_model = models.ForeignKey(SomeModel, on_delete=models.CASCADE) number = models.IntegerField() def do_something(self): diff --git a/test/input/func_noerror_foreign_key_sets.py b/test/input/func_noerror_foreign_key_sets.py index b68eccaf..22ce18bc 100644 --- a/test/input/func_noerror_foreign_key_sets.py +++ b/test/input/func_noerror_foreign_key_sets.py @@ -18,11 +18,12 @@ def get_first(self): class OtherModel(models.Model): count = models.IntegerField() - something = models.ForeignKey(SomeModel) + something = models.ForeignKey(SomeModel, on_delete=models.CASCADE) class ThirdModel(models.Model): - whatever = models.ForeignKey(SomeModel, related_name='whatevs') + whatever = models.ForeignKey(SomeModel, related_name='whatevs', + on_delete=models.CASCADE) def count_whatevers(): diff --git a/test/input/func_noerror_foreignkeys.py b/test/input/func_noerror_foreignkeys.py index 296076a9..ec5401f4 100644 --- a/test/input/func_noerror_foreignkeys.py +++ b/test/input/func_noerror_foreignkeys.py @@ -17,8 +17,8 @@ class ISBN(models.Model): class Book(models.Model): book_name = models.CharField(max_length=100) - author = models.ForeignKey(Author) - isbn = models.OneToOneField(ISBN) + author = models.ForeignKey(Author, on_delete=models.CASCADE) + isbn = models.OneToOneField(ISBN, on_delete=models.CASCADE) def get_isbn(self): return self.isbn.value @@ -32,7 +32,7 @@ class Fruit(models.Model): class Seed(models.Model): - fruit = ForeignKey(Fruit) + fruit = ForeignKey(Fruit, on_delete=models.CASCADE) def get_fruit_name(self): return self.fruit.fruit_name @@ -43,7 +43,7 @@ class User(models.Model): class UserProfile(models.Model): - user = OneToOneField(User) + user = OneToOneField(User, on_delete=models.CASCADE) def get_username(self): return self.user.username From 10d612a6a0356d0d9c1217c549f369911b178c82 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 15:10:18 +0200 Subject: [PATCH 06/26] Remove missing IPAddressField b/c we test with Django 1.11+ --- test/input/func_noerror_form_fields.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/input/func_noerror_form_fields.py b/test/input/func_noerror_form_fields.py index 28ceace6..2a910727 100644 --- a/test/input/func_noerror_form_fields.py +++ b/test/input/func_noerror_form_fields.py @@ -21,9 +21,6 @@ class ManyFieldsForm(forms.Form): floatfield = forms.FloatField() genericipaddressfield = forms.GenericIPAddressField() imagefield = forms.ImageField(name='test_image', upload_to='test') - # note: IPAdressField has been deprecated since django 1.7 so might not - # be available if using django 1.8+ - ipaddressfield = getattr(forms, 'IPAddressField', 'GenericIPAddressField')() intfield = forms.IntegerField(null=True) nullbooleanfield = forms.NullBooleanField() slugfield = forms.SlugField() From fd68bc1a83820d687bce410198a5e59a98272ac7 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 15:31:41 +0200 Subject: [PATCH 07/26] Disable augmentations for missing R0924 badly-implemeted-container --- pylint_django/augmentations/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pylint_django/augmentations/__init__.py b/pylint_django/augmentations/__init__.py index 23eb1cdd..9bc12571 100644 --- a/pylint_django/augmentations/__init__.py +++ b/pylint_django/augmentations/__init__.py @@ -721,9 +721,10 @@ def apply_augmentations(linter): suppress_message(linter, _visit_class(ClassChecker), 'W0232', is_class('django.forms.models.ModelForm')) # forms implement __getitem__ but not __len__, thus raising a "Badly implemented container" warning which - # we will suppress. - suppress_message(linter, _leave_class(MisdesignChecker), 'R0924', is_class('django.forms.forms.Form')) - suppress_message(linter, _leave_class(MisdesignChecker), 'R0924', is_class('django.forms.models.ModelForm')) + # we will suppress. NOTE: removed from pylint, https://github.com/PyCQA/pylint/issues/112 + # keeping here in case it gets re-implemented + # suppress_message(linter, _leave_class(MisdesignChecker), 'R0924', is_class('django.forms.forms.Form')) + # suppress_message(linter, _leave_class(MisdesignChecker), 'R0924', is_class('django.forms.models.ModelForm')) # Meta suppress_message(linter, _visit_class(DocStringChecker), 'missing-docstring', is_model_meta_subclass) From 85bf1b70385c3b45575cdefafb47c02b102f5ddf Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 16:54:58 +0200 Subject: [PATCH 08/26] Remove R0903 too-few-public-methods from test files the plugin should be able to suppress these kinds of errors for model classes and also for Meta classes so no need to disable them explicitly. --- test/external_drf/func_noerror_serializer.py | 2 +- test/input/func_noerror_forms_py33.py | 2 +- test/input/func_noerror_forms_py_28.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/external_drf/func_noerror_serializer.py b/test/external_drf/func_noerror_serializer.py index 5b045a3d..6442f84a 100644 --- a/test/external_drf/func_noerror_serializer.py +++ b/test/external_drf/func_noerror_serializer.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about DRF serializers """ -# pylint: disable=C0111,W5101,R0903 +# pylint: disable=C0111,W5101 from rest_framework import serializers diff --git a/test/input/func_noerror_forms_py33.py b/test/input/func_noerror_forms_py33.py index abc87c00..38912282 100644 --- a/test/input/func_noerror_forms_py33.py +++ b/test/input/func_noerror_forms_py33.py @@ -1,7 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=missing-docstring,R0903,wrong-import-position +# pylint: disable=missing-docstring,wrong-import-position from django import forms diff --git a/test/input/func_noerror_forms_py_28.py b/test/input/func_noerror_forms_py_28.py index 7dbf25d4..976a57a7 100644 --- a/test/input/func_noerror_forms_py_28.py +++ b/test/input/func_noerror_forms_py_28.py @@ -1,8 +1,7 @@ """ Checks that Pylint does not complain about django Forms """ -# pylint: disable=missing-docstring,R0903 - +# pylint: disable=missing-docstring from django import forms From 4b39e90f530a7dd7f308da18fea5cf4b39a75cb4 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 17:40:46 +0200 Subject: [PATCH 09/26] Use human readable name for suppressed message also remove couple of suppressions b/c these class checks are already handled by the check for meta class and they don't seem to have any effect --- pylint_django/augmentations/__init__.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pylint_django/augmentations/__init__.py b/pylint_django/augmentations/__init__.py index 9bc12571..616d196c 100644 --- a/pylint_django/augmentations/__init__.py +++ b/pylint_django/augmentations/__init__.py @@ -715,7 +715,7 @@ def apply_augmentations(linter): suppress_message(linter, _visit_attribute(TypeChecker), 'E1101', generic_is_view_attribute(parents, attrs)) # formviews have too many ancestors, there's nothing the user of the library can do about that - suppress_message(linter, _visit_class(MisdesignChecker), 'R0901', is_class('django.views.generic.edit.FormView')) + suppress_message(linter, _visit_class(MisdesignChecker), 'too-many-ancestors', is_class('django.views.generic.edit.FormView')) # model forms have no __init__ method anywhere in their bases suppress_message(linter, _visit_class(ClassChecker), 'W0232', is_class('django.forms.models.ModelForm')) @@ -740,14 +740,6 @@ def apply_augmentations(linter): suppress_message(linter, _visit_class(ClassChecker), 'no-init', is_model_media_subclass) suppress_message(linter, _leave_class(MisdesignChecker), 'too-few-public-methods', is_model_media_subclass) - # Too few public methods started appearing for Views and Models as part of Pylint>=1.4 / astroid>=1.3.3 - # Not sure why, suspect this is a failure to get the parent classes somewhere - # For now, just suppress it on models and views - suppress_message(linter, _leave_class(MisdesignChecker), 'too-few-public-methods', - is_class('.Model')) - suppress_message(linter, _leave_class(MisdesignChecker), 'too-few-public-methods', - is_class('.View')) - # Admin # Too many public methods (40+/20) # TODO: Count public methods of django.contrib.admin.options.ModelAdmin and increase From 8376e28f1161c2813e495c18c03e92b241a3a707 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Thu, 18 Jan 2018 11:51:03 +0200 Subject: [PATCH 10/26] Remove unused tox configuration --- tox.ini | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 tox.ini diff --git a/tox.ini b/tox.ini deleted file mode 100644 index bb88cbbf..00000000 --- a/tox.ini +++ /dev/null @@ -1,7 +0,0 @@ -[tox] -envlist = py27,py33,py34,py35 - -[testenv] -deps=Django -commands=python test/test_func.py - From cd1f67dc54c1067878f0beae1ddab5085c86eabe Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 17:55:29 +0200 Subject: [PATCH 11/26] Add failure notifications for Travis CI --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8a1983d9..534d1df4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,3 +19,7 @@ script: - PYTHONPATH=. coverage run test/test_func.py after_success: coveralls +notifications: + email: + on_failure: change + on_success: never From 5bb7be27ce015e2e74b692cae4831260367ed5b7 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 15:08:08 +0200 Subject: [PATCH 12/26] Drop support for testing on Python 2 --- .travis.yml | 4 --- setup.py | 5 ++- .../func_model_requires_unicode_py_28.py | 22 ------------ test/input/func_model_unicode_parent_py_28.py | 15 -------- test/input/func_noerror_forms_py_28.py | 32 ----------------- test/input/func_noerror_models_py_28.py | 34 ------------------- .../func_model_requires_unicode_py_28.txt | 1 - .../func_model_unicode_parent_py_28.txt | 1 - 8 files changed, 2 insertions(+), 112 deletions(-) delete mode 100644 test/input/func_model_requires_unicode_py_28.py delete mode 100644 test/input/func_model_unicode_parent_py_28.py delete mode 100644 test/input/func_noerror_forms_py_28.py delete mode 100644 test/input/func_noerror_models_py_28.py delete mode 100644 test/messages/func_model_requires_unicode_py_28.txt delete mode 100644 test/messages/func_model_unicode_parent_py_28.txt diff --git a/.travis.yml b/.travis.yml index 534d1df4..138da8ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,6 @@ python: env: - DJANGO="1.11,<2.0" - DJANGO="2.0,<3.0" -matrix: - include: - - python: 2.7 - env: DJANGO="1.11,<2.0" install: - pip install coverage coveralls diff --git a/setup.py b/setup.py index 2e77228b..c74e6d1a 100644 --- a/setup.py +++ b/setup.py @@ -25,10 +25,9 @@ 'Intended Audience :: Developers', 'Operating System :: Unix', 'Topic :: Software Development :: Quality Assurance', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ) diff --git a/test/input/func_model_requires_unicode_py_28.py b/test/input/func_model_requires_unicode_py_28.py deleted file mode 100644 index 45322112..00000000 --- a/test/input/func_model_requires_unicode_py_28.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -Ensures that django models without a __unicode__ method are flagged, -but only models which are not abstract -""" -# pylint: disable=missing-docstring - -from django.db import models - - -class SomeModel(models.Model): - something = models.CharField(max_length=255) - # no __unicode__ method - - something.something_else = 1 - - def lala(self): - pass - - -class SomeAbstractModel(models.Model): - class Meta: - abstract = True diff --git a/test/input/func_model_unicode_parent_py_28.py b/test/input/func_model_unicode_parent_py_28.py deleted file mode 100644 index 42844038..00000000 --- a/test/input/func_model_unicode_parent_py_28.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Ensures that django models whose parent have a -__unicide__ method are not flagged -""" -# pylint: disable=missing-docstring -from django.db import models - - -class MyModel(models.Model): - def __unicode__(self): - return str(self.id) - - -class MySubclassModel(MyModel): - pass diff --git a/test/input/func_noerror_forms_py_28.py b/test/input/func_noerror_forms_py_28.py deleted file mode 100644 index 976a57a7..00000000 --- a/test/input/func_noerror_forms_py_28.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Checks that Pylint does not complain about django Forms -""" -# pylint: disable=missing-docstring -from django import forms - - -class TestForm(forms.Form): - class Meta: - pass - - some_field = forms.CharField() - - def clean(self): - print self.cleaned_data - print self.fields - print self.error_class - - -class TestModelForm(forms.ModelForm): - class Meta: - pass - - -class TestFormSubclass(forms.Form): - class Meta: - pass - - -class TestModelFormSubclass(forms.ModelForm): - class Meta: - pass diff --git a/test/input/func_noerror_models_py_28.py b/test/input/func_noerror_models_py_28.py deleted file mode 100644 index c5405906..00000000 --- a/test/input/func_noerror_models_py_28.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Checks that Pylint does not complain about a fairly standard -Django Model -""" -# pylint: disable=missing-docstring -from django.db import models - - -class SomeModel(models.Model): - class Meta: - pass - - some_field = models.CharField(max_length=20) - - other_fields = models.ManyToManyField('AnotherModel') - - def stuff(self): - try: - print self._meta - print self.other_fields.all()[0] - except self.DoesNotExist: - print 'does not exist' - except self.MultipleObjectsReturned: - print 'lala' - - print self.get_some_field_display() - - def __unicode__(self): - print 'some model %s' % self.id - - -class SubclassModel(SomeModel): - class Meta: - pass diff --git a/test/messages/func_model_requires_unicode_py_28.txt b/test/messages/func_model_requires_unicode_py_28.txt deleted file mode 100644 index 91be4bd9..00000000 --- a/test/messages/func_model_requires_unicode_py_28.txt +++ /dev/null @@ -1 +0,0 @@ -W: 10:SomeModel: No __unicode__ method on model (SomeModel) diff --git a/test/messages/func_model_unicode_parent_py_28.txt b/test/messages/func_model_unicode_parent_py_28.txt deleted file mode 100644 index 918c0bea..00000000 --- a/test/messages/func_model_unicode_parent_py_28.txt +++ /dev/null @@ -1 +0,0 @@ -W: 14:MySubclassModel: Model does not explicitly define __unicode__ (MySubclassModel) \ No newline at end of file From bec095f2eb7e458b50f430d94b0fa36f4f8dbf6d Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 22:02:57 +0200 Subject: [PATCH 13/26] Update comments in test --- test/input/func_model_does_not_use_unicode_py33.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/input/func_model_does_not_use_unicode_py33.py b/test/input/func_model_does_not_use_unicode_py33.py index 459082b7..fe9afb9d 100644 --- a/test/input/func_model_does_not_use_unicode_py33.py +++ b/test/input/func_model_does_not_use_unicode_py33.py @@ -1,5 +1,5 @@ """ -Ensures that django models without a __unicode__ method are flagged +Ensures that under PY3 django models with a __unicode__ method are flagged """ # pylint: disable=missing-docstring @@ -8,7 +8,7 @@ class SomeModel(models.Model): something = models.CharField(max_length=255) - # no __unicode__ method + # no __str__ method something.something_else = 1 From 893d72be8f73e307f3e0747b3ab176bc4f64c341 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 22:22:08 +0200 Subject: [PATCH 14/26] Enable test case which is Django 1.8+ this was previously skipped but since we don't test on older versions we can explicitly add it again. --- ...teted_meta_access.py => func_noerror_protected_meta_access.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/input/{versions/func_noerror_proteted_meta_access.py => func_noerror_protected_meta_access.py} (100%) diff --git a/test/input/versions/func_noerror_proteted_meta_access.py b/test/input/func_noerror_protected_meta_access.py similarity index 100% rename from test/input/versions/func_noerror_proteted_meta_access.py rename to test/input/func_noerror_protected_meta_access.py From a8f668bcb9b3b5696c7f8f97f7d973da1eb9fc53 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 22:38:41 +0200 Subject: [PATCH 15/26] Update format of expected error messages for unicode test the latest version of pylint expects the error messages in slightly different format. --- test/input/func_model_does_not_use_unicode_py33.py | 2 +- test/input/func_model_does_not_use_unicode_py33.txt | 1 + test/messages/func_model_does_not_use_unicode_py33.txt | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 test/input/func_model_does_not_use_unicode_py33.txt delete mode 100644 test/messages/func_model_does_not_use_unicode_py33.txt diff --git a/test/input/func_model_does_not_use_unicode_py33.py b/test/input/func_model_does_not_use_unicode_py33.py index fe9afb9d..0b28841e 100644 --- a/test/input/func_model_does_not_use_unicode_py33.py +++ b/test/input/func_model_does_not_use_unicode_py33.py @@ -6,7 +6,7 @@ from django.db import models -class SomeModel(models.Model): +class SomeModel(models.Model): # [model-has-unicode] something = models.CharField(max_length=255) # no __str__ method diff --git a/test/input/func_model_does_not_use_unicode_py33.txt b/test/input/func_model_does_not_use_unicode_py33.txt new file mode 100644 index 00000000..8d3d8bb4 --- /dev/null +++ b/test/input/func_model_does_not_use_unicode_py33.txt @@ -0,0 +1 @@ +model-has-unicode:9:SomeModel:Found __unicode__ method on model (SomeModel). Python3 uses __str__. diff --git a/test/messages/func_model_does_not_use_unicode_py33.txt b/test/messages/func_model_does_not_use_unicode_py33.txt deleted file mode 100644 index 711cbcc6..00000000 --- a/test/messages/func_model_does_not_use_unicode_py33.txt +++ /dev/null @@ -1 +0,0 @@ -W: 9:SomeModel: Found __unicode__ method on model (SomeModel). Python3 uses __str__. \ No newline at end of file From 18c8f73a26e09126d5f1f2fab9d82aa806e8ab5c Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 22:48:22 +0200 Subject: [PATCH 16/26] Enable test for django-rest-framework serializer --- .travis.yml | 2 +- .../external_drf_noerror_serializer.py} | 1 - test/input/external_drf_noerror_serializer.rc | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) rename test/{external_drf/func_noerror_serializer.py => input/external_drf_noerror_serializer.py} (99%) create mode 100644 test/input/external_drf_noerror_serializer.rc diff --git a/.travis.yml b/.travis.yml index 138da8ec..4ad70fa7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: - DJANGO="2.0,<3.0" install: - - pip install coverage coveralls + - pip install coverage coveralls djangorestframework - pip install "Django>=$DJANGO" - pip install git+https://github.com/landscapeio/pylint-plugin-utils.git@master script: diff --git a/test/external_drf/func_noerror_serializer.py b/test/input/external_drf_noerror_serializer.py similarity index 99% rename from test/external_drf/func_noerror_serializer.py rename to test/input/external_drf_noerror_serializer.py index 6442f84a..c4bc7da8 100644 --- a/test/external_drf/func_noerror_serializer.py +++ b/test/input/external_drf_noerror_serializer.py @@ -8,4 +8,3 @@ class TestSerializerSubclass(serializers.ModelSerializer): class Meta: pass - diff --git a/test/input/external_drf_noerror_serializer.rc b/test/input/external_drf_noerror_serializer.rc new file mode 100644 index 00000000..a63d6bff --- /dev/null +++ b/test/input/external_drf_noerror_serializer.rc @@ -0,0 +1,2 @@ +[testoptions] +requires = rest_framework From 527221c536db8930ed50a4ae53fa43cf29f7854c Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Tue, 16 Jan 2018 23:05:39 +0200 Subject: [PATCH 17/26] Use PYTHONPATH for the shell script referenced in README --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index ad93a9a9..32d97261 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1,2 +1,2 @@ #!/bin/bash -python test/test_func.py +PYTHONPATH=. python test/test_func.py From 81e82941884f1156db896f859bd596544ee3db6d Mon Sep 17 00:00:00 2001 From: Vinay Pai Date: Wed, 27 Dec 2017 14:51:26 -0500 Subject: [PATCH 18/26] Add common names to good_names instead of modifying const_rgx for compatiblity with pylint 1.8+ Fixes https://github.com/landscapeio/pylint-django/issues/108 Original PR: https://github.com/landscapeio/pylint-django/pull/109 Obsolete PR: https://github.com/landscapeio/pylint-django/pull/111 --- pylint_django/plugin.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pylint_django/plugin.py b/pylint_django/plugin.py index e24ef33c..65bf1a59 100644 --- a/pylint_django/plugin.py +++ b/pylint_django/plugin.py @@ -16,13 +16,7 @@ def register(linter): However, we will also use it to amend existing checker config. """ name_checker = get_checker(linter, NameChecker) - name_checker.config.good_names += ('qs',) - - # Default pylint.checkers.base.CONST_NAME_RGX = re.compile('(([A-Z_][A-Z0-9_]*)|(__.*__))$'). - start = name_checker.config.const_rgx.pattern[:-2] - end = name_checker.config.const_rgx.pattern[-2:] - const_rgx = '%s|(urls|urlpatterns|register)%s' % (start, end) - name_checker.config.const_rgx = re.compile(const_rgx) + name_checker.config.good_names += ('qs', 'urlpatterns', 'register', 'app_name') # we don't care about South migrations linter.config.black_list += ('migrations', 'south_migrations') From 5f14ada43873b4be7ab3d60ee6c056946d014583 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Wed, 17 Jan 2018 15:39:54 +0200 Subject: [PATCH 19/26] Add handler500 to good_names --- pylint_django/plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pylint_django/plugin.py b/pylint_django/plugin.py index 65bf1a59..668c4be4 100644 --- a/pylint_django/plugin.py +++ b/pylint_django/plugin.py @@ -16,7 +16,8 @@ def register(linter): However, we will also use it to amend existing checker config. """ name_checker = get_checker(linter, NameChecker) - name_checker.config.good_names += ('qs', 'urlpatterns', 'register', 'app_name') + name_checker.config.good_names += ('qs', 'urlpatterns', 'register', 'app_name', + 'handler500') # we don't care about South migrations linter.config.black_list += ('migrations', 'south_migrations') From 0797e73825c23da685f452a42e1d64a46ba08f0b Mon Sep 17 00:00:00 2001 From: Konstantinos Koukopoulos Date: Tue, 17 Oct 2017 15:47:23 +0300 Subject: [PATCH 20/26] Support factory_boy's DjangoModelFactory Meta class Added suppressions for [DjangoModelFactory](http://factoryboy.readthedocs.io/en/2.9.2/orms.html#the-djangomodelfactory-subclass). Original PR: https://github.com/landscapeio/pylint-django/pull/103 --- pylint_django/augmentations/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pylint_django/augmentations/__init__.py b/pylint_django/augmentations/__init__.py index 616d196c..2b54f263 100644 --- a/pylint_django/augmentations/__init__.py +++ b/pylint_django/augmentations/__init__.py @@ -407,6 +407,16 @@ def is_model_meta_subclass(node): return node_is_subclass(node.parent, *parents) +def is_model_factory_meta_subclass(node): + """Checks that node is derivative of DjangoModelFactory class.""" + if node.name != 'Meta' or not isinstance(node.parent, ClassDef): + return False + + parents = ('factory.django.DjangoModelFactory', + '.DjangoModelFactory',) + return node_is_subclass(node.parent, *parents) + + def is_model_mpttmeta_subclass(node): """Checks that node is derivative of MPTTMeta class.""" if node.name != 'MPTTMeta' or not isinstance(node.parent, ClassDef): @@ -765,6 +775,12 @@ def apply_augmentations(linter): suppress_message(linter, _visit_class(ClassChecker), 'W0232', is_model_mpttmeta_subclass) suppress_message(linter, _leave_class(MisdesignChecker), 'too-few-public-methods', is_model_mpttmeta_subclass) + # factory_boy's DjangoModelFactory + suppress_message(linter, _visit_class(DocStringChecker), 'missing-docstring', is_model_factory_meta_subclass) + suppress_message(linter, _visit_class(NewStyleConflictChecker), 'old-style-class', is_model_factory_meta_subclass) + suppress_message(linter, _visit_class(ClassChecker), 'W0232', is_model_factory_meta_subclass) + suppress_message(linter, _leave_class(MisdesignChecker), 'too-few-public-methods', is_model_factory_meta_subclass) + # ForeignKey and OneToOneField # Must update this in a thread safe way to support the parallel option on pylint (-j) current_leave_module = VariablesChecker.leave_module From ce00090c730e0b70547867a0ed1e3955df4bafa6 Mon Sep 17 00:00:00 2001 From: canarduck Date: Mon, 14 Aug 2017 16:27:18 +0200 Subject: [PATCH 21/26] Create func_noerror_ugettext_lazy_format.py Checks that Pylint does not complain about django lazy proxy when using ugettext_lazy --- test/input/func_noerror_ugettext_lazy_format.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 test/input/func_noerror_ugettext_lazy_format.py diff --git a/test/input/func_noerror_ugettext_lazy_format.py b/test/input/func_noerror_ugettext_lazy_format.py new file mode 100644 index 00000000..1e8ad248 --- /dev/null +++ b/test/input/func_noerror_ugettext_lazy_format.py @@ -0,0 +1,7 @@ +""" +Checks that Pylint does not complain about django lazy proxy +when using ugettext_lazy +""" +from django.utils.translation import ugettext_lazy + +ugettext_lazy('{something}').format(something='lala') From e9975b52fdb79ef9a769331c7e3b549ea0323f69 Mon Sep 17 00:00:00 2001 From: canarduck Date: Mon, 14 Aug 2017 16:33:16 +0200 Subject: [PATCH 22/26] ugettext_lazy is supposed to return six.text_type Fix E1101:Instance of '__proxy__' has no 'format' member' when using .format() on a ugettext_lazy translation NOTE: merged with modifications. Instead of returning str, returns '' Fixes https://github.com/landscapeio/pylint-django/issues/80 Origina PR: https://github.com/landscapeio/pylint-django/pull/100 --- pylint_django/transforms/transforms/django_utils_translation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint_django/transforms/transforms/django_utils_translation.py b/pylint_django/transforms/transforms/django_utils_translation.py index c838edef..70d7274c 100644 --- a/pylint_django/transforms/transforms/django_utils_translation.py +++ b/pylint_django/transforms/transforms/django_utils_translation.py @@ -1 +1 @@ -ugettext_lazy = lambda x: None +ugettext_lazy = lambda x: '' From d1e36636974deca1b618071add25cfa26ec0acd1 Mon Sep 17 00:00:00 2001 From: "James M. Allen" Date: Tue, 8 Aug 2017 10:12:38 -0400 Subject: [PATCH 23/26] Adding tests and transforms for DurationField Original PR: https://github.com/landscapeio/pylint-django/pull/99 Fixes https://github.com/landscapeio/pylint-django/issues/95 --- pylint_django/transforms/fields.py | 2 ++ .../transforms/transforms/django_db_models_fields.py | 6 ++++++ .../transforms/transforms/django_forms_fields.py | 8 +++++++- test/input/func_noerror_form_fields.py | 6 ++++++ test/input/func_noerror_model_fields.py | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pylint_django/transforms/fields.py b/pylint_django/transforms/fields.py index ec311155..5a22dfda 100644 --- a/pylint_django/transforms/fields.py +++ b/pylint_django/transforms/fields.py @@ -45,6 +45,8 @@ def apply_type_shim(cls, context=None): # noqa base_nodes = MANAGER.ast_from_module_name('datetime').lookup('time') elif cls.name == 'DateField': base_nodes = MANAGER.ast_from_module_name('datetime').lookup('date') + elif cls.name == 'DurationField': + base_nodes = MANAGER.ast_from_module_name('datetime').lookup('timedelta') elif cls.name == 'ManyToManyField': base_nodes = MANAGER.ast_from_module_name('django.db.models.query').lookup('QuerySet') elif cls.name in ('ImageField', 'FileField'): diff --git a/pylint_django/transforms/transforms/django_db_models_fields.py b/pylint_django/transforms/transforms/django_db_models_fields.py index 0f1b6106..a0208fc0 100644 --- a/pylint_django/transforms/transforms/django_db_models_fields.py +++ b/pylint_django/transforms/transforms/django_db_models_fields.py @@ -110,6 +110,12 @@ def __new__(cls, verbose_name=None, name=None, auto_now=False, pass +class DurationField(datetime.timedelta, django_fields.DurationField): + if PY3: + def __new__(cls, verbose_name=None, name=None, **kwargs): + pass + + # ------- # misc diff --git a/pylint_django/transforms/transforms/django_forms_fields.py b/pylint_django/transforms/transforms/django_forms_fields.py index 18105429..4ace966d 100644 --- a/pylint_django/transforms/transforms/django_forms_fields.py +++ b/pylint_django/transforms/transforms/django_forms_fields.py @@ -101,7 +101,13 @@ def __new__(cls, input_formats=None, *args, **kwargs): pass - # -------- +class DurationField(datetime.timedelta, django_fields.DurationField): + if PY3: + def __new__(cls, *args, **kwargs): + pass + + +# -------- # choice class ChoiceField(object, django_fields.ChoiceField): diff --git a/test/input/func_noerror_form_fields.py b/test/input/func_noerror_form_fields.py index 2a910727..7ddb4ff5 100644 --- a/test/input/func_noerror_form_fields.py +++ b/test/input/func_noerror_form_fields.py @@ -15,6 +15,7 @@ class ManyFieldsForm(forms.Form): datetimefield = forms.DateTimeField(auto_now_add=True) datefield = forms.DateField(auto_now_add=True) decimalfield = forms.DecimalField(max_digits=5, decimal_places=2) + durationfield = forms.DurationField() emailfield = forms.EmailField() filefield = forms.FileField(name='test_file', upload_to='test') filepathfield = forms.FilePathField(path='/some/path') @@ -57,6 +58,11 @@ def datefield_tests(self): def decimalfield_tests(self): print(self.decimalfield.adjusted()) + def durationfield_tests(self): + now = datetime.now() + print(now - self.durationfield) + print(self.durationfield.total_seconds()) + def filefield_tests(self): print(self.filefield) print(self.imagefield) diff --git a/test/input/func_noerror_model_fields.py b/test/input/func_noerror_model_fields.py index d30bb1cd..08145fe5 100644 --- a/test/input/func_noerror_model_fields.py +++ b/test/input/func_noerror_model_fields.py @@ -18,6 +18,7 @@ class LotsOfFieldsModel(models.Model): datetimefield = models.DateTimeField(auto_now_add=True) datefield = models.DateField(auto_now_add=True) decimalfield = models.DecimalField(max_digits=5, decimal_places=2) + durationfield = models.DurationField() emailfield = models.EmailField() filefield = models.FileField(name='test_file', upload_to='test') filepathfield = models.FilePathField() @@ -69,6 +70,11 @@ def datefield_tests(self): def decimalfield_tests(self): print(self.decimalfield.compare(Decimal('1.4'))) + def durationfield_tests(self): + now = datetime.now() + print(now - self.durationfield) + print(self.durationfield.total_seconds()) + def filefield_tests(self): print(self.filefield.file) print(self.imagefield.file) From 4241d9d056a965ad4d89182d5945e64cf9581f95 Mon Sep 17 00:00:00 2001 From: sjk4sc Date: Thu, 9 Mar 2017 10:52:59 -0600 Subject: [PATCH 24/26] Add json field to WSGIRequest proxy Original PR: https://github.com/landscapeio/pylint-django/pull/92 --- pylint_django/transforms/transforms/django_core_handlers_wsgi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylint_django/transforms/transforms/django_core_handlers_wsgi.py b/pylint_django/transforms/transforms/django_core_handlers_wsgi.py index f8c4ef37..b9e6df53 100644 --- a/pylint_django/transforms/transforms/django_core_handlers_wsgi.py +++ b/pylint_django/transforms/transforms/django_core_handlers_wsgi.py @@ -4,3 +4,4 @@ class WSGIRequest(WSGIRequestOriginal): status_code = None content = '' + json = None From e5767ed6a3cb8cda99ee6bf2c2c09df2c5e1a8c2 Mon Sep 17 00:00:00 2001 From: Villiers Strauss Date: Thu, 15 Sep 2016 11:17:07 +0200 Subject: [PATCH 25/26] add support for django.contrib.postgres.fields and also UUIDField NOTE: merged with modifications: - resolved conflicts - updated where test files are on disk Original PR: https://github.com/landscapeio/pylint-django/pull/84 --- .travis.yml | 2 +- pylint_django/transforms/fields.py | 13 ++++- .../django_contrib_postgres_fields.py | 47 +++++++++++++++++ .../transforms/django_db_models_fields.py | 5 ++ test/__init__.py | 0 ...ternal_psycopg2_noerror_postgres_fields.py | 52 +++++++++++++++++++ ...ternal_psycopg2_noerror_postgres_fields.rc | 2 + test/input/func_noerror_uuid_field.py | 19 +++++++ 8 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 pylint_django/transforms/transforms/django_contrib_postgres_fields.py create mode 100644 test/__init__.py create mode 100644 test/input/external_psycopg2_noerror_postgres_fields.py create mode 100644 test/input/external_psycopg2_noerror_postgres_fields.rc create mode 100644 test/input/func_noerror_uuid_field.py diff --git a/.travis.yml b/.travis.yml index 4ad70fa7..ea495b37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: - DJANGO="2.0,<3.0" install: - - pip install coverage coveralls djangorestframework + - pip install coverage coveralls djangorestframework psycopg2 - pip install "Django>=$DJANGO" - pip install git+https://github.com/landscapeio/pylint-plugin-utils.git@master script: diff --git a/pylint_django/transforms/fields.py b/pylint_django/transforms/fields.py index 5a22dfda..1e3a5a8f 100644 --- a/pylint_django/transforms/fields.py +++ b/pylint_django/transforms/fields.py @@ -9,10 +9,13 @@ _INT_FIELDS = ('IntegerField', 'SmallIntegerField', 'BigIntegerField', 'PositiveIntegerField', 'PositiveSmallIntegerField') _BOOL_FIELDS = ('BooleanField', 'NullBooleanField') +_RANGE_FIELDS = ('RangeField', 'IntegerRangeField', 'BigIntegerRangeField', + 'FloatRangeField', 'DateTimeRangeField', 'DateRangeField') def is_model_field(cls): - return cls.qname().startswith('django.db.models.fields') + return cls.qname().startswith('django.db.models.fields') or \ + cls.qname().startswith('django.contrib.postgres.fields') def is_form_field(cls): @@ -47,10 +50,18 @@ def apply_type_shim(cls, context=None): # noqa base_nodes = MANAGER.ast_from_module_name('datetime').lookup('date') elif cls.name == 'DurationField': base_nodes = MANAGER.ast_from_module_name('datetime').lookup('timedelta') + elif cls.name == 'UUIDField': + base_nodes = MANAGER.ast_from_module_name('uuid').lookup('UUID') elif cls.name == 'ManyToManyField': base_nodes = MANAGER.ast_from_module_name('django.db.models.query').lookup('QuerySet') elif cls.name in ('ImageField', 'FileField'): base_nodes = MANAGER.ast_from_module_name('django.core.files.base').lookup('File') + elif cls.name == 'ArrayField': + base_nodes = scoped_nodes.builtin_lookup('list') + elif cls.name in ('HStoreField', 'JSONField'): + base_nodes = scoped_nodes.builtin_lookup('dict') + elif cls.name in _RANGE_FIELDS: + base_nodes = MANAGER.ast_from_module_name('psycopg2._range').lookup('Range') else: return iter([cls]) diff --git a/pylint_django/transforms/transforms/django_contrib_postgres_fields.py b/pylint_django/transforms/transforms/django_contrib_postgres_fields.py new file mode 100644 index 00000000..64c9a229 --- /dev/null +++ b/pylint_django/transforms/transforms/django_contrib_postgres_fields.py @@ -0,0 +1,47 @@ +from django.contrib.postgres import fields as django_fields +from psycopg2 import extras + + +# -------- +# lists + +class ArrayField(list, django_fields.ArrayField): + pass + + +# -------- +# dicts + +class HStoreField(dict, django_fields.HStoreField): + pass + + +class JSONField(dict, django_fields.JSONField): + pass + + +# -------- +# ranges + +class RangeField(extras.Range, django_fields.RangeField): + pass + + +class IntegerRangeField(extras.NumericRange, django_fields.IntegerRangeField): + pass + + +class BigIntegerRangeField(extras.NumericRange, django_fields.BigIntegerRangeField): + pass + + +class FloatRangeField(extras.NumericRange, django_fields.FloatRangeField): + pass + + +class DateTimeRangeField(extras.DateTimeTZRange, django_fields.DateRangeField): + pass + + +class DateRangeField(extras.DateRange, django_fields.DateRangeField): + pass diff --git a/pylint_django/transforms/transforms/django_db_models_fields.py b/pylint_django/transforms/transforms/django_db_models_fields.py index a0208fc0..f8cf12e4 100644 --- a/pylint_django/transforms/transforms/django_db_models_fields.py +++ b/pylint_django/transforms/transforms/django_db_models_fields.py @@ -1,6 +1,7 @@ from django.db.models import fields as django_fields import datetime from decimal import Decimal +from uuid import UUID # -------- @@ -125,3 +126,7 @@ class GenericIPAddressField(str, django_fields.GenericIPAddressField): class IPAddressField(str, django_fields.IPAddressField): pass + + +class UUIDField(UUID, django_fields.UUIDField): + pass diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/input/external_psycopg2_noerror_postgres_fields.py b/test/input/external_psycopg2_noerror_postgres_fields.py new file mode 100644 index 00000000..e5cb0dde --- /dev/null +++ b/test/input/external_psycopg2_noerror_postgres_fields.py @@ -0,0 +1,52 @@ +""" +Checks that Pylint does not complain Postgres model fields. +""" +# pylint: disable=C0111,W5101 +from __future__ import print_function + +from django.contrib.postgres import fields +from django.db import models + + +class PostgresFieldsModel(models.Model): + arrayfield = fields.ArrayField(models.CharField()) + hstorefield = fields.HStoreField() + jsonfield = fields.JSONField() + rangefield = fields.RangeField() + integerrangefield = fields.IntegerRangeField() + bigintegerrangefield = fields.BigIntegerRangeField() + floatrangefield = fields.FloatRangeField() + datetimerangefield = fields.DateTimeRangeField() + daterangefield = fields.DateRangeField() + + def arrayfield_tests(self): + sorted_array = self.arrayfield.sort() + print(sorted_array) + + def dictfield_tests(self): + print(self.hstorefield.keys()) + print(self.hstorefield.values()) + print(self.hstorefield.update({'foo': 'bar'})) + + print(self.jsonfield.keys()) + print(self.jsonfield.values()) + print(self.jsonfield.update({'foo': 'bar'})) + + def rangefield_tests(self): + print(self.rangefield.lower) + print(self.rangefield.upper) + + print(self.integerrangefield.lower) + print(self.integerrangefield.upper) + + print(self.bigintegerrangefield.lower) + print(self.bigintegerrangefield.upper) + + print(self.floatrangefield.lower) + print(self.floatrangefield.upper) + + print(self.datetimerangefield.lower) + print(self.datetimerangefield.upper) + + print(self.daterangefield.lower) + print(self.daterangefield.upper) diff --git a/test/input/external_psycopg2_noerror_postgres_fields.rc b/test/input/external_psycopg2_noerror_postgres_fields.rc new file mode 100644 index 00000000..79f0c092 --- /dev/null +++ b/test/input/external_psycopg2_noerror_postgres_fields.rc @@ -0,0 +1,2 @@ +[testoptions] +requires = psycopg2 diff --git a/test/input/func_noerror_uuid_field.py b/test/input/func_noerror_uuid_field.py new file mode 100644 index 00000000..1fa5b12c --- /dev/null +++ b/test/input/func_noerror_uuid_field.py @@ -0,0 +1,19 @@ +""" +Checks that Pylint does not complain about UUID fields. +""" +# pylint: disable=C0111,W5101 +from __future__ import print_function +from django.db import models + + +class LotsOfFieldsModel(models.Model): + uuidfield = models.UUIDField() + + def uuidfield_tests(self): + print(self.uuidfield.bytes) + print(self.uuidfield.bytes_le) + print(self.uuidfield.fields[2]) + print(self.uuidfield.hex) + # print(self.uuidfield.int) # Don't know how to properly check this one + print(self.uuidfield.variant) + print(self.uuidfield.version) From f6a5ac2131987d75636b64255755c6ae2dd7108d Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Thu, 18 Jan 2018 11:42:40 +0200 Subject: [PATCH 26/26] Update changelog --- CHANGELOG.md | 25 +++++++++++++++++++++++++ CONTRIBUTORS.md | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed288aeb..43abd892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## Version 0.8.0 (unreleased) + +* [#109](http://github.com/landscapeio/pylint-django/pull/109), + adding 'urlpatterns', 'register', 'app_name' to good names. Obsoletes + [#111](http://github.com/landscapeio/pylint-django/pull/111), fixes + [#108](http://github.com/landscapeio/pylint-django/issues/108) + (Vinay Pai) +* Add 'handler500' to good names (Mr. Senko) +* [#103](http://github.com/landscapeio/pylint-django/pull/103): + Support factory_boy's DjangoModelFactory Meta class (Konstantinos Koukopoulos) +* [#100](https://github.com/landscapeio/pylint-django/pull/100): + Fix E1101:Instance of '__proxy__' has no 'format' member' when using .format() + on a ugettext_lazy translation. Fixes + [#80](https://github.com/landscapeio/pylint-django/issues/80) (canarduck) +* [#99](https://github.com/landscapeio/pylint-django/pull/99): + Add tests and transforms for DurationField, fixes + [#95](https://github.com/landscapeio/pylint-django/issues/95) (James M. Allen) +* [#92](https://github.com/landscapeio/pylint-django/pull/92): + Add json field to WSGIRequest proxy (sjk4sc) +* [#84](https://github.com/landscapeio/pylint-django/pull/84): + Add support for django.contrib.postgres.fields and UUIDField (Villiers Strauss) +* Stop testing with older Django versions. Currently testing with Django 1.11.x and 2.0 +* Stop testing on Python 2, no functional changes in the source code though +* Update tests for latest version of pylint (>=1.8) + ## Version 0.7.4 * [#88](https://github.com/landscapeio/pylint-django/pull/88) Fixed builds with Django 1.10 (thanks to [federicobond](https://github.com/federicobond)) * [#91](https://github.com/landscapeio/pylint-django/pull/91) Fixed race condition when running with pylint parallel execution mode (thanks to [jeremycarroll](https://github.com/jeremycarroll)) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e3515a83..8f82e36d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -5,4 +5,5 @@ * [jproffitt](https://github.com/jproffitt) * [lhupfeldt](https://github.com/lhupfeldt) * [smirolo](https://github.com/smirolo) -* [mbertolacci](https://github.com/mbertolacci) \ No newline at end of file +* [mbertolacci](https://github.com/mbertolacci) +* [atodorov](https://github.com/atodorov)