From ad81fdf7069b768d931489e338c6ed1f260aa5b5 Mon Sep 17 00:00:00 2001 From: Adrian Turjak Date: Wed, 5 Feb 2020 11:41:32 +1300 Subject: [PATCH] Update to Django 2.2, drop py2 support OpenStack is dropping the py2.7 support in Ussuri cycle. Adjutant is also upgrading to Django 2.2 at the same time which is the new Django LTS, and only supports python 3. Complete discussion & schedule can be found in - http://lists.openstack.org/pipermail/openstack-discuss/2019-October/010142.html - https://etherpad.openstack.org/p/drop-python2-support Ussuri Communtiy-wide goal: https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html Ussuri Communtiy-wide goal: https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html Change-Id: I2a429ebd6bc20385e814da03b222a1f61214a683 --- .zuul.yaml | 1 - adjutant/actions/migrations/0001_initial.py | 2 +- adjutant/actions/models.py | 2 +- adjutant/api/migrations/0001_initial.py | 4 +-- .../api/migrations/0005_auto_20190610_0209.py | 2 ++ adjutant/api/models.py | 4 +-- adjutant/middleware.py | 30 ++++++++++++++----- adjutant/settings.py | 19 +++++------- .../notes/django-2-2-465a8bb124f1f7fe.yaml | 12 ++++++++ requirements.txt | 7 ++--- setup.cfg | 3 +- tox.ini | 2 +- 12 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml diff --git a/.zuul.yaml b/.zuul.yaml index 044e493..0ab006a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -3,5 +3,4 @@ - publish-openstack-docs-pti - build-release-notes-jobs-python3 - openstack-cover-jobs - - openstack-python-jobs - openstack-python3-ussuri-jobs diff --git a/adjutant/actions/migrations/0001_initial.py b/adjutant/actions/migrations/0001_initial.py index 650c1dc..d737692 100644 --- a/adjutant/actions/migrations/0001_initial.py +++ b/adjutant/actions/migrations/0001_initial.py @@ -25,7 +25,7 @@ class Migration(migrations.Migration): ('need_token', models.BooleanField(default=False)), ('order', models.IntegerField()), ('created', models.DateTimeField(default=django.utils.timezone.now)), - ('task', models.ForeignKey(to='api.Task')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task')), ], ), ] diff --git a/adjutant/actions/models.py b/adjutant/actions/models.py index c0c3e98..036b601 100644 --- a/adjutant/actions/models.py +++ b/adjutant/actions/models.py @@ -30,7 +30,7 @@ class Action(models.Model): state = models.CharField(max_length=200, default="default") valid = models.BooleanField(default=False) need_token = models.BooleanField(default=False) - task = models.ForeignKey('tasks.Task') + task = models.ForeignKey('tasks.Task', on_delete=models.CASCADE) # NOTE(amelia): Auto approve is technically a ternary operator # If all in a task are None it will not auto approve # However if at least one action has it set to True it diff --git a/adjutant/api/migrations/0001_initial.py b/adjutant/api/migrations/0001_initial.py index 49784d4..9b5679d 100644 --- a/adjutant/api/migrations/0001_initial.py +++ b/adjutant/api/migrations/0001_initial.py @@ -47,12 +47,12 @@ class Migration(migrations.Migration): ('token', models.CharField(max_length=32, serialize=False, primary_key=True)), ('created_on', models.DateTimeField(default=django.utils.timezone.now)), ('expires', models.DateTimeField(db_index=True)), - ('task', models.ForeignKey(to='api.Task')), + ('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task')), ], ), migrations.AddField( model_name='notification', name='task', - field=models.ForeignKey(to='api.Task'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Task'), ), ] diff --git a/adjutant/api/migrations/0005_auto_20190610_0209.py b/adjutant/api/migrations/0005_auto_20190610_0209.py index a654ce6..9f7568b 100644 --- a/adjutant/api/migrations/0005_auto_20190610_0209.py +++ b/adjutant/api/migrations/0005_auto_20190610_0209.py @@ -7,6 +7,8 @@ from django.db import migrations class Migration(migrations.Migration): + atomic = False + dependencies = [ ('api', '0004_auto_20160929_0317'), ] diff --git a/adjutant/api/models.py b/adjutant/api/models.py index b13d8fc..db79e95 100644 --- a/adjutant/api/models.py +++ b/adjutant/api/models.py @@ -29,7 +29,7 @@ class Token(models.Model): UUID token object bound to a task. """ - task = models.ForeignKey(Task) + task = models.ForeignKey(Task, on_delete=models.CASCADE) token = models.CharField(max_length=32, primary_key=True) created_on = models.DateTimeField(default=timezone.now) expires = models.DateTimeField(db_index=True) @@ -56,7 +56,7 @@ class Notification(models.Model): uuid = models.CharField(max_length=32, default=hex_uuid, primary_key=True) notes = JSONField(default={}) - task = models.ForeignKey(Task) + task = models.ForeignKey(Task, on_delete=models.CASCADE) error = models.BooleanField(default=False, db_index=True) created_on = models.DateTimeField(default=timezone.now) acknowledged = models.BooleanField(default=False, db_index=True) diff --git a/adjutant/middleware.py b/adjutant/middleware.py index 92f9c65..25fe16e 100644 --- a/adjutant/middleware.py +++ b/adjutant/middleware.py @@ -17,12 +17,15 @@ from logging import getLogger from django.utils import timezone -class KeystoneHeaderUnwrapper(object): +class KeystoneHeaderUnwrapper: """ Middleware to build an easy to use dict of important data from what the keystone wsgi middleware gives us. """ - def process_request(self, request): + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): try: token_data = { 'project_domain_id': request.META['HTTP_X_PROJECT_DOMAIN_ID'], @@ -38,12 +41,18 @@ class KeystoneHeaderUnwrapper(object): token_data = {} request.keystone_user = token_data + response = self.get_response(request) + return response -class TestingHeaderUnwrapper(object): + +class TestingHeaderUnwrapper: """ Replacement for the KeystoneHeaderUnwrapper for testing purposes. """ - def process_request(self, request): + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): try: token_data = { # TODO(adriant): follow up patch to update all the test @@ -65,17 +74,21 @@ class TestingHeaderUnwrapper(object): token_data = {} request.keystone_user = token_data + response = self.get_response(request) + return response -class RequestLoggingMiddleware(object): + +class RequestLoggingMiddleware: """ Middleware to log the requests and responses. Will time the duration of a request and log that. """ - def __init__(self): + def __init__(self, get_response): + self.get_response = get_response self.logger = getLogger('adjutant') - def process_request(self, request): + def __call__(self, request): self.logger.info( '(%s) - <%s> %s [%s]', timezone.now(), @@ -85,7 +98,8 @@ class RequestLoggingMiddleware(object): ) request.timer = time() - def process_response(self, request, response): + response = self.get_response(request) + if hasattr(request, 'timer'): time_delta = time() - request.timer else: diff --git a/adjutant/settings.py b/adjutant/settings.py index d18d87f..51f8042 100644 --- a/adjutant/settings.py +++ b/adjutant/settings.py @@ -33,7 +33,6 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # Application definition INSTALLED_APPS = ( - 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -50,23 +49,17 @@ INSTALLED_APPS = ( 'adjutant.startup', ) -MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', +MIDDLEWARE = ( 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'adjutant.middleware.KeystoneHeaderUnwrapper', 'adjutant.middleware.RequestLoggingMiddleware' ) if 'test' in sys.argv: - # modify MIDDLEWARE_CLASSES - MIDDLEWARE_CLASSES = list(MIDDLEWARE_CLASSES) - MIDDLEWARE_CLASSES.remove('adjutant.middleware.KeystoneHeaderUnwrapper') - MIDDLEWARE_CLASSES.append('adjutant.middleware.TestingHeaderUnwrapper') + # modify MIDDLEWARE + MIDDLEWARE = list(MIDDLEWARE) + MIDDLEWARE.remove('adjutant.middleware.KeystoneHeaderUnwrapper') + MIDDLEWARE.append('adjutant.middleware.TestingHeaderUnwrapper') ROOT_URLCONF = 'adjutant.urls' @@ -98,6 +91,8 @@ TEMPLATES = [ }, ] +AUTHENTICATION_BACKENDS = [] + REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'adjutant.api.exception_handler.exception_handler', 'DEFAULT_RENDERER_CLASSES': [ diff --git a/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml b/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml new file mode 100644 index 0000000..a10edfc --- /dev/null +++ b/releasenotes/notes/django-2-2-465a8bb124f1f7fe.yaml @@ -0,0 +1,12 @@ +--- +upgrade: + - | + Adjutant will now officially only support Python3.6 onwards, and will + start introducing features only applicable to that version onwards. +deprecations: + - | + Python2 support has been officially deprecated. The code may still be + compatible for a bit longer, but we are also switching to Django 2.2, + and python2 can no longer be tested. Support for Python less than 3.6 + has also been deprecated, but may still work for older python3 versions + for a little longer, although not officially. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 04ea756..cfc10da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ pbr>=5.2.0 +Django>=2.2,<2.3 Babel>=2.6.0 decorator>=4.4.0 django-rest-swagger>=2.2.0 @@ -15,8 +16,4 @@ python-octaviaclient>=1.8.0 PyYAML>=5.1 six>=1.12.0 confspirator>=0.1.6 - -# Address soon: -Django>=1.11,<1.12 -# was pinned because of django 1.11 -mysqlclient>=1.3.10,<1.4 +mysqlclient>=1.4.6 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 2b309a9..5cd7ca0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,8 +16,7 @@ classifier = Intended Audience :: Developers Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License - Framework :: Django :: 1.11 - Programming Language :: Python :: 2.7 + Framework :: Django :: 2.2 Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 diff --git a/tox.ini b/tox.ini index b1344b1..51275a9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py3,py27,pep8,cover_report +envlist = py3,pep8,cover_report skipsdist = True [testenv]