Repository: Nitrate/Nitrate

Issue:
Make it work with Django 3.0

Make it work with Django 3.0



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -14,10 +14,10 @@ def get_long_description():
 
 install_requires = [
     'beautifulsoup4 >= 4.1.1',
-    'django >= 2.1,<3.0',
-    'django-contrib-comments == 1.9.1',
+    'django >= 2.1,<3.1',
+    'django-contrib-comments == 1.9.2',
     'django-tinymce == 2.7.0',
-    'django-uuslug == 1.1.8',
+    'django-uuslug == 1.2.0',
     'html2text',
     'odfpy >= 0.9.6',
     'python-bugzilla',
@@ -91,6 +91,7 @@ def get_long_description():
         'Framework :: Django',
         'Framework :: Django :: 2.1',
         'Framework :: Django :: 2.2',
+        'Framework :: Django :: 3.0',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
         'Programming Language :: Python :: 3',
diff --git a/src/tcms/issuetracker/models.py b/src/tcms/issuetracker/models.py
--- a/src/tcms/issuetracker/models.py
+++ b/src/tcms/issuetracker/models.py
@@ -12,7 +12,6 @@
 from django.core.validators import MaxLengthValidator, RegexValidator
 from django.db import models
 from django.db.models import Count
-from django.utils.encoding import python_2_unicode_compatible
 
 from tcms.core.models import TCMSActionModel
 from tcms.issuetracker import validators
@@ -43,7 +42,6 @@ class CredentialTypes(enum.Enum):
     Token = 'Token based'
 
 
-@python_2_unicode_compatible
 class IssueTrackerProduct(TCMSActionModel):
     """Representing a specific issue tracker product
 
@@ -71,7 +69,6 @@ def import_service_class(self):
         return getattr(module, class_name)
 
 
-@python_2_unicode_compatible
 class ProductIssueTrackerRelationship(TCMSActionModel):
     """Many-to-many relationship between Product and IssueTracker
 
@@ -111,7 +108,6 @@ class Meta:
         unique_together = ('product', 'issue_tracker')
 
 
-@python_2_unicode_compatible
 class IssueTracker(TCMSActionModel):
     """Represent a deployed issue tracker instance"""
 
@@ -407,7 +403,6 @@ def clean(self):
             self.check_secret_file(self.secret_file)
 
 
-@python_2_unicode_compatible
 class UserPwdCredential(Credential):
     """Username/password credential for logging into issue tracker"""
 
@@ -458,7 +453,6 @@ def clean(self):
                 raise ValidationError({'password': 'Missing password.'})
 
 
-@python_2_unicode_compatible
 class TokenCredential(Credential):
     """Token based authentication for logging into issue tracker"""
 
@@ -508,7 +502,6 @@ def clean(self):
                 raise ValidationError('Expiration date is prior to today.')
 
 
-@python_2_unicode_compatible
 class Issue(TCMSActionModel):
     """This is the issue which could be added to case or case run
 


Test patch:
diff --git a/src/tests/testcases/test_models.py b/src/tests/testcases/test_models.py
--- a/src/tests/testcases/test_models.py
+++ b/src/tests/testcases/test_models.py
@@ -145,9 +145,7 @@ def test_remove_plan(self):
         self.new_case.remove_plan(self.plan)
 
         found = self.plan.case.filter(pk=self.new_case.pk).exists()
-        self.assertFalse(
-            found, 'Case {0} should has no relationship to plan {0} now.'.format(self.new_case.pk,
-                                                                                 self.plan.pk))
+        self.assertFalse(found)
 
 
 class TestCaseRemoveTag(BasePlanCase):
diff --git a/src/tests/testcases/test_views.py b/src/tests/testcases/test_views.py
--- a/src/tests/testcases/test_views.py
+++ b/src/tests/testcases/test_views.py
@@ -1794,7 +1794,7 @@ def test_invalid_arguments(self):
         msgs = sorted(data['message'])
         self.assertIn(
             f'Nonexistent component id(s) {nonexisting_component_id}', msgs[0])
-        self.assertIn(f'Nonexistent product id', msgs[1])
+        self.assertIn('Nonexistent product id', msgs[1])
 
     @patch('tcms.testcases.models.TestCase.add_component')
     def test_failed_to_add_component(self, add_component):