From 441fefb86394fcb5b90766874c71f140c93fe2fa Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Fri, 7 Dec 2018 12:17:23 +0200 Subject: [PATCH 1/5] Drop support for obsolete Djangos, add Django 2.1 & Python 3.7 --- .travis.yml | 9 +++++---- tox.ini | 8 +++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6df0d83..1e196cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,24 @@ -sudo: false +dist: xenial language: python python: + - "3.7" - "3.6" - "3.5" - "2.7" env: matrix: + - DJANGO_VERSION=2.1 - DJANGO_VERSION=2.0 - DJANGO_VERSION=1.11 - - DJANGO_VERSION=1.10 - - DJANGO_VERSION=1.9 - - DJANGO_VERSION=1.8 matrix: exclude: - python: "2.7" env: DJANGO_VERSION=2.0 + - python: "2.7" + env: DJANGO_VERSION=2.1 install: - pip install tox coveralls diff --git a/tox.ini b/tox.ini index 26017dd..f1f3377 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] envlist = covclean, - py27-dj{18,19,110,111}, - py{35,36}-dj{18,19,110,111,20}, + py27-dj111, + py{35,36,37}-dj{111,20,21}, coverage [testenv] @@ -10,11 +10,9 @@ setenv = PYTHONPATH = {toxinidir}:{toxinidir}/watchman commands = coverage run --parallel --source watchman runtests.py {posargs} deps = - dj18: Django>=1.8,<1.9 - dj19: Django>=1.9,<1.10 - dj110: Django>=1.10,<1.11 dj111: Django>=1.11,<2.0 dj20: Django>=2.0,<2.1 + dj21: Django>=2.1,<2.2 -r{toxinidir}/requirements-test.txt [testenv:covclean] From 49614610ff2c4ae355ed08c21e3764faf59aa2d7 Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Fri, 7 Dec 2018 12:18:45 +0200 Subject: [PATCH 2/5] Update classifiers with tested Python versions --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9ab1b6b..36b8f62 100755 --- a/setup.py +++ b/setup.py @@ -49,9 +49,10 @@ 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', ], ) From 10c9593460e43c52c9659ab93481e9b6336ac709 Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Fri, 7 Dec 2018 12:31:11 +0200 Subject: [PATCH 3/5] Optimize Docker image size a bit --- .dockerignore | 5 +++++ Dockerfile | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2d07030 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +.tox +*.egg_info +**/__pycache__ +**/*.pyc diff --git a/Dockerfile b/Dockerfile index 728f8cd..a246bca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM python +FROM python:slim COPY . /app WORKDIR /app/sample_project -RUN pip install -r requirements.txt +RUN pip install --no-cache -r requirements.txt RUN python manage.py migrate CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] From f8b1bee27ceb055430fb09de52e177a4c346072e Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Fri, 7 Dec 2018 12:38:53 +0200 Subject: [PATCH 4/5] Regenerate sample project with latest Django LTS (1.11) --- sample_project/manage.py | 18 ++++++-- sample_project/requirements.txt | 2 +- sample_project/sample_project/settings.py | 56 +++++++++++------------ sample_project/sample_project/urls.py | 17 ++++++- sample_project/sample_project/wsgi.py | 2 +- 5 files changed, 60 insertions(+), 35 deletions(-) diff --git a/sample_project/manage.py b/sample_project/manage.py index 9c651f3..db62fa4 100755 --- a/sample_project/manage.py +++ b/sample_project/manage.py @@ -4,7 +4,19 @@ if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample_project.settings") - - from django.core.management import execute_from_command_line - + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise execute_from_command_line(sys.argv) diff --git a/sample_project/requirements.txt b/sample_project/requirements.txt index 08b6b5f..8a72e2a 100644 --- a/sample_project/requirements.txt +++ b/sample_project/requirements.txt @@ -1,4 +1,4 @@ -django<1.9 +django<2.0,>=1.11 # django-watchman -e /app diff --git a/sample_project/sample_project/settings.py b/sample_project/sample_project/settings.py index a26a9dd..60ad29b 100644 --- a/sample_project/sample_project/settings.py +++ b/sample_project/sample_project/settings.py @@ -1,23 +1,23 @@ """ Django settings for sample_project project. -Generated by 'django-admin startproject' using Django 1.8.6. +Generated by 'django-admin startproject' using Django 1.11.17. For more information on this file, see -https://docs.djangoproject.com/en/1.8/topics/settings/ +https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.8/ref/settings/ +https://docs.djangoproject.com/en/1.11/ref/settings/ """ -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'h%n@34@2nst!bm-ilj$3tfyq4-*iq@q@0_jjquu4$0g61ep-vy' @@ -34,7 +34,7 @@ # Application definition -INSTALLED_APPS = ( +INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -42,18 +42,17 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'watchman', -) +] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', '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', - 'django.middleware.security.SecurityMiddleware', -) +] ROOT_URLCONF = 'sample_project.urls' @@ -77,7 +76,7 @@ # Database -# https://docs.djangoproject.com/en/1.8/ref/settings/#databases +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { @@ -91,28 +90,27 @@ } -# Logging -# https://docs.djangoproject.com/en/1.8/topics/logging/ +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', - }, +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, - 'loggers': { - 'watchman': { - 'handlers': ['console'], - 'level': 'DEBUG', - }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, -} + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] # Internationalization -# https://docs.djangoproject.com/en/1.8/topics/i18n/ +# https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -126,6 +124,6 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.8/howto/static-files/ +# https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' diff --git a/sample_project/sample_project/urls.py b/sample_project/sample_project/urls.py index 79949b5..3112489 100644 --- a/sample_project/sample_project/urls.py +++ b/sample_project/sample_project/urls.py @@ -1,10 +1,25 @@ +"""sample_project URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" from django.conf.urls import include, url from django.contrib import admin import watchman.views urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), url(r'^watchman/', include('watchman.urls')), url(r'^watchman/bare/', watchman.views.bare_status, name='bare_status'), ] diff --git a/sample_project/sample_project/wsgi.py b/sample_project/sample_project/wsgi.py index d32b7ee..e825f20 100644 --- a/sample_project/sample_project/wsgi.py +++ b/sample_project/sample_project/wsgi.py @@ -4,7 +4,7 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ """ import os From adad187fe9334472036af06e41cbd0fc89e88882 Mon Sep 17 00:00:00 2001 From: Jamie Hewland Date: Fri, 7 Dec 2018 12:48:27 +0200 Subject: [PATCH 5/5] Travis: Skip release build if no tag --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1e196cf..6300d42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ notifications: jobs: include: - stage: pypi release + if: tag IS present python: "3.6" script: echo "Deploying to pypi ..." deploy: