Hello community,
here is the log from the commit of package python-django-webtest for
openSUSE:Factory checked in at 2018-12-11 15:49:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-webtest (Old)
and /work/SRC/openSUSE:Factory/.python-django-webtest.new.19453 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-webtest"
Tue Dec 11 15:49:44 2018 rev:2 rq:657149 version:1.9.4
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-django-webtest/python-django-webtest.changes
2017-12-23 12:19:57.350209902 +0100
+++
/work/SRC/openSUSE:Factory/.python-django-webtest.new.19453/python-django-webtest.changes
2018-12-11 15:49:48.334075762 +0100
@@ -1,0 +2,13 @@
+Tue Dec 11 11:36:29 UTC 2018 - Tomáš Chvátal <[email protected]>
+
+- Version update to 1.9.4:
+ * allow to use positionnal args; fixed #89
+ * remove deprecated pytest.yield_fixture functions. use pytest.fixture
instead; fixed #88
+ * Don't add duplicate WebtestUserMiddleware to the list of middlewares in
WebTestMixin. fixed #87
+ * restore MIDDLEWARE_CLASSES support; fixed #84
+ * Passing user=None to get/post/etc. methods will clear a user previously
set with set_user instead of doing nothing.
+ * Avoid sharing settings between tests in pytest plugin
+ * Fix middleware settings name used
+- Enable tests
+
+-------------------------------------------------------------------
Old:
----
django-webtest-1.9.2.tar.gz
New:
----
django-webtest-1.9.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-webtest.spec ++++++
--- /var/tmp/diff_new_pack.8f7j4r/_old 2018-12-11 15:49:49.770074176 +0100
+++ /var/tmp/diff_new_pack.8f7j4r/_new 2018-12-11 15:49:49.774074171 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-django-webtest
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,21 +12,27 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-django-webtest
-Version: 1.9.2
+Version: 1.9.4
Release: 0
Summary: Django integration for WebTest
License: MIT
Group: Development/Languages/Python
-Url: https://github.com/django-webtest/django-webtest
+URL: https://github.com/django-webtest/django-webtest
Source:
https://files.pythonhosted.org/packages/source/d/django-webtest/django-webtest-%{version}.tar.gz
+BuildRequires: %{python_module Django}
+BuildRequires: %{python_module WebTest >= 1.3.3}
+BuildRequires: %{python_module pytest-django}
+BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
+BuildRequires: fdupes
BuildRequires: python-rpm-macros
+Requires: python-Django
Requires: python-WebTest >= 1.3.3
%python_subpackages
@@ -41,9 +47,16 @@
%install
%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
+
+%check
+pushd django_webtest_tests
+%python_exec runtests.py
+popd
%files %{python_files}
-%doc AUTHORS.txt CHANGES.rst LICENSE.txt README.rst
+%license LICENSE.txt
+%doc AUTHORS.txt CHANGES.rst README.rst
%{python_sitelib}/*
%changelog
++++++ django-webtest-1.9.2.tar.gz -> django-webtest-1.9.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/CHANGES.rst
new/django-webtest-1.9.4/CHANGES.rst
--- old/django-webtest-1.9.2/CHANGES.rst 2017-05-17 10:52:10.000000000
+0200
+++ new/django-webtest-1.9.4/CHANGES.rst 2018-10-27 10:58:09.000000000
+0200
@@ -2,6 +2,32 @@
CHANGES
=======
+1.9.4 (2018-10-27)
+------------------
+
+- py34 and Django 1.8 are no longer tested (but may works)
+
+- allow to use positionnal args; fixed #89
+
+- remove deprecated pytest.yield_fixture functions. use pytest.fixture instead;
+ fixed #88
+
+- Don't add duplicate WebtestUserMiddleware to the list of middlewares in
+ WebTestMixin. fixed #87
+
+- restore MIDDLEWARE_CLASSES support; fixed #84
+
+1.9.3 (2018-05-03)
+------------------
+
+- Passing `user=None` to get/post/etc. methods will clear a user
+ previously set with `set_user` instead of doing nothing.
+
+- Avoid sharing settings between tests in pytest plugin
+
+- Fix middleware settings name used
+
+
1.9.2 (2017-05-17)
------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/PKG-INFO
new/django-webtest-1.9.4/PKG-INFO
--- old/django-webtest-1.9.2/PKG-INFO 2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/PKG-INFO 2018-10-27 10:58:09.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: django-webtest
-Version: 1.9.2
+Version: 1.9.4
Summary: Instant integration of Ian Bicking's WebTest
(http://docs.pylonsproject.org/projects/webtest/) with django's testing
framework.
Home-page: https://github.com/django-webtest/django-webtest
Author: Mikhail Korobov
@@ -63,11 +63,14 @@
(``django_webtest.WebTest``) that creates ``webtest.TestApp`` around
django wsgi interface and makes it available in tests as ``self.app``.
- It also features optional ``user`` argument for ``self.app.get`` and
- ``self.app.post`` methods to help making authorized requests. This
argument
+ It also features an optional ``user`` argument for ``self.app.get``,
+ ``self.app.post``, etc. to help making authorized requests. This
argument
should be a django.contrib.auth.models.User instance or a string with
user's
``username`` for the user who is supposed to be logged in. To log out
again,
- call ``self.app.reset``, clearing all cookies.
+ call ``self.app.reset``, clearing all cookies. To make a bunch of
calls
+ with the same user, call ``app.set_user(user)`` before your requests;
if
+ you want to disable that user, call ``app.get(..., user=None)`` for one
+ request or ``app.set_user(None)`` to unset the user for all following
calls.
For 500 errors original traceback is shown instead of usual html result
from handler500.
@@ -105,6 +108,7 @@
class MyTestCase(WebTest):
csrf_checks = False
+
def test_post(self)
self.app.post('/')
@@ -180,6 +184,32 @@
CHANGES
=======
+ 1.9.4 (2018-10-27)
+ ------------------
+
+ - py34 and Django 1.8 are no longer tested (but may works)
+
+ - allow to use positionnal args; fixed #89
+
+ - remove deprecated pytest.yield_fixture functions. use pytest.fixture
instead;
+ fixed #88
+
+ - Don't add duplicate WebtestUserMiddleware to the list of middlewares
in
+ WebTestMixin. fixed #87
+
+ - restore MIDDLEWARE_CLASSES support; fixed #84
+
+ 1.9.3 (2018-05-03)
+ ------------------
+
+ - Passing `user=None` to get/post/etc. methods will clear a user
+ previously set with `set_user` instead of doing nothing.
+
+ - Avoid sharing settings between tests in pytest plugin
+
+ - Fix middleware settings name used
+
+
1.9.2 (2017-05-17)
------------------
@@ -440,12 +470,11 @@
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/README.rst
new/django-webtest-1.9.4/README.rst
--- old/django-webtest-1.9.2/README.rst 2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/README.rst 2018-10-27 10:58:09.000000000 +0200
@@ -55,11 +55,14 @@
(``django_webtest.WebTest``) that creates ``webtest.TestApp`` around
django wsgi interface and makes it available in tests as ``self.app``.
-It also features optional ``user`` argument for ``self.app.get`` and
-``self.app.post`` methods to help making authorized requests. This argument
+It also features an optional ``user`` argument for ``self.app.get``,
+``self.app.post``, etc. to help making authorized requests. This argument
should be a django.contrib.auth.models.User instance or a string with user's
``username`` for the user who is supposed to be logged in. To log out again,
-call ``self.app.reset``, clearing all cookies.
+call ``self.app.reset``, clearing all cookies. To make a bunch of calls
+with the same user, call ``app.set_user(user)`` before your requests; if
+you want to disable that user, call ``app.get(..., user=None)`` for one
+request or ``app.set_user(None)`` to unset the user for all following calls.
For 500 errors original traceback is shown instead of usual html result
from handler500.
@@ -97,6 +100,7 @@
class MyTestCase(WebTest):
csrf_checks = False
+
def test_post(self)
self.app.post('/')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest/__init__.py
new/django-webtest-1.9.4/django_webtest/__init__.py
--- old/django-webtest-1.9.2/django_webtest/__init__.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest/__init__.py 2018-10-27
10:58:09.000000000 +0200
@@ -33,6 +33,10 @@
from django_webtest.compat import to_string, to_wsgi_safe_string
+# sentinel to differentiate user=None / user param not given
+_notgiven = object()
+
+
class DjangoTestApp(TestApp):
response_class = DjangoWebtestResponse
@@ -43,24 +47,30 @@
def get_wsgi_handler(self):
return StaticFilesHandler(WSGIHandler())
- def set_user(self, user=None):
- """Update the user used by the app globaly. If user is None then user
- is unset"""
+ def set_user(self, user):
+ """Update the user used by the app globall; pass None to unset."""
if user is None and 'WEBTEST_USER' in self.extra_environ:
del self.extra_environ['WEBTEST_USER']
if user is not None:
self.extra_environ = self._update_environ(self.extra_environ, user)
- def _update_environ(self, environ, user=None):
+ def _update_environ(self, environ, user=_notgiven):
environ = environ or {}
environ.setdefault('HTTP_HOST', 'testserver')
- if user:
- username = _get_username(user)
- environ['WEBTEST_USER'] = to_wsgi_safe_string(username)
+
+ if user is not _notgiven:
+ if user is None:
+ # We can't just delete the key here, the test request is built
+ # from self.extra_environ + this environ, so the header defined
+ # by set_user will be found in self.extra_environ.
+ environ['WEBTEST_USER'] = ''
+ else:
+ username = _get_username(user)
+ environ['WEBTEST_USER'] = to_wsgi_safe_string(username)
+
return environ
def do_request(self, req, status, expect_errors):
-
# Django closes the database connection after every request;
# this breaks the use of transactions in your tests.
if close_old_connections is not None: # Django 1.6+
@@ -115,13 +125,13 @@
else: # Django < 1.6
signals.request_finished.connect(close_connection)
- def get(self, url, **kwargs):
+ def get(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
auto_follow = kwargs.pop('auto_follow', False)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- response = super(DjangoTestApp, self).get(url, **kwargs)
+ response = super(DjangoTestApp, self).get(url, *args, **kwargs)
def is_redirect(r):
return r.status_int >= 300 and r.status_int < 400
@@ -130,65 +140,65 @@
return response
- def post(self, url, **kwargs):
+ def post(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).post(url, **kwargs)
+ return super(DjangoTestApp, self).post(url, *args, **kwargs)
- def put(self, url, **kwargs):
+ def put(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).put(url, **kwargs)
+ return super(DjangoTestApp, self).put(url, *args, **kwargs)
- def patch(self, url, **kwargs):
+ def patch(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).patch(url, **kwargs)
+ return super(DjangoTestApp, self).patch(url, *args, **kwargs)
- def head(self, url, **kwargs):
+ def head(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).head(url, **kwargs)
+ return super(DjangoTestApp, self).head(url, *args, **kwargs)
- def options(self, url, **kwargs):
+ def options(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).options(url, **kwargs)
+ return super(DjangoTestApp, self).options(url, *args, **kwargs)
- def delete(self, url, **kwargs):
+ def delete(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).delete(url, **kwargs)
+ return super(DjangoTestApp, self).delete(url, *args, **kwargs)
- def post_json(self, url, **kwargs):
+ def post_json(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).post_json(url, **kwargs)
+ return super(DjangoTestApp, self).post_json(url, *args, **kwargs)
- def put_json(self, url, **kwargs):
+ def put_json(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).put_json(url, **kwargs)
+ return super(DjangoTestApp, self).put_json(url, *args, **kwargs)
- def patch_json(self, url, **kwargs):
+ def patch_json(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).patch_json(url, **kwargs)
+ return super(DjangoTestApp, self).patch_json(url, *args, **kwargs)
- def delete_json(self, url, **kwargs):
+ def delete_json(self, url, *args, **kwargs):
extra_environ = kwargs.get('extra_environ')
- user = kwargs.pop('user', None)
+ user = kwargs.pop('user', _notgiven)
kwargs['extra_environ'] = self._update_environ(extra_environ, user)
- return super(DjangoTestApp, self).delete_json(url, **kwargs)
+ return super(DjangoTestApp, self).delete_json(url, *args, **kwargs)
@property
def session(self):
@@ -206,8 +216,8 @@
self.extra_environ = self._update_environ(self.extra_environ)
return super(DjangoTestApp, self).set_cookie(*args, **kwargs)
-class WebTestMixin(object):
+class WebTestMixin(object):
extra_environ = {}
csrf_checks = True
setup_auth = True
@@ -262,10 +272,9 @@
# middleware to the end. If appending causes problems
# _setup_auth_middleware method can be overriden by a subclass.
self.settings_middleware.append(webtest_auth_middleware)
- else:
+ elif webtest_auth_middleware not in self.settings_middleware:
index = self.settings_middleware.index(django_auth_middleware)
- self.settings_middleware.insert(index + 1,
- webtest_auth_middleware)
+ self.settings_middleware.insert(index + 1, webtest_auth_middleware)
def _setup_auth_backend(self):
backend_name = 'django_webtest.backends.WebtestUserBackend'
@@ -276,7 +285,7 @@
try:
return self._middleware_setting_name
except AttributeError:
- if hasattr(settings, 'MIDDLEWARE') and settings.MIDDLEWARE:
+ if getattr(settings, 'MIDDLEWARE', None) is not None:
name = 'MIDDLEWARE'
else:
name = 'MIDDLEWARE_CLASSES'
@@ -319,9 +328,17 @@
Return user's username. ``user`` can be standard Django User
instance, a custom user model or just an username (as string).
"""
- if hasattr(user, 'get_username'): # custom user, django 1.5+
- return user.get_username()
- elif hasattr(user, 'username'): # standard User
- return user.username
- else: # assume user is just an username
- return user
+ value = None
+ # custom user, django 1.5+
+ get_username = getattr(user, 'get_username', None)
+ if get_username is not None:
+ value = get_username()
+ if value is None:
+ # standard User
+ username = getattr(user, 'username', None)
+ if username is not None:
+ value = username
+ else:
+ # assume user is just an username
+ value = user
+ return value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest/backends.py
new/django-webtest-1.9.4/django_webtest/backends.py
--- old/django-webtest-1.9.2/django_webtest/backends.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest/backends.py 2018-10-27
10:58:09.000000000 +0200
@@ -1,7 +1,7 @@
from __future__ import absolute_import
from django.utils.version import get_complete_version
from django.contrib.auth.backends import RemoteUserBackend
-from .compat import from_wsgi_safe_string
+from django_webtest.compat import from_wsgi_safe_string
class WebtestUserBackend(RemoteUserBackend):
""" Auth backend for django-webtest auth system """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest/compat.py
new/django-webtest-1.9.4/django_webtest/compat.py
--- old/django-webtest-1.9.2/django_webtest/compat.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest/compat.py 2018-10-27
10:58:09.000000000 +0200
@@ -36,3 +36,9 @@
if django.VERSION < (1, 10):
return user.is_authenticated()
return user.is_authenticated
+
+
+def is_anonymous(user):
+ if django.VERSION < (1, 10):
+ return user.is_anonymous()
+ return user.is_anonymous
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest/middleware.py
new/django-webtest-1.9.4/django_webtest/middleware.py
--- old/django-webtest-1.9.2/django_webtest/middleware.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest/middleware.py 2018-10-27
10:58:09.000000000 +0200
@@ -8,7 +8,7 @@
else:
MiddlewareMixin = object
-from .compat import is_authenticated
+from django_webtest.compat import is_authenticated
class WebtestUserMiddleware(RemoteUserMiddleware):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest/pytest_plugin.py
new/django-webtest-1.9.4/django_webtest/pytest_plugin.py
--- old/django-webtest-1.9.2/django_webtest/pytest_plugin.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest/pytest_plugin.py 2018-10-27
10:58:09.000000000 +0200
@@ -3,13 +3,25 @@
import pytest
+class MixinWithInstanceVariables(WebTestMixin):
+ """
+ Override WebTestMixin to make all of its variables instance variables
+ not class variables; otherwise multiple django_app_factory fixtures contend
+ for the same class variables
+ """
+ def __init__(self):
+ self.extra_environ = {}
+ self.csrf_checks = True
+ self.setup_auth = True
+
+
@pytest.fixture(scope='session')
def django_app_mixin():
- app_mixin = WebTestMixin()
+ app_mixin = MixinWithInstanceVariables()
return app_mixin
[email protected]_fixture
[email protected]
def django_app(django_app_mixin):
django_app_mixin._patch_settings()
django_app_mixin.renew_app()
@@ -17,11 +29,10 @@
django_app_mixin._unpatch_settings()
[email protected]_fixture
[email protected]
def django_app_factory():
- app_mixin = WebTestMixin()
-
def factory(csrf_checks=True, extra_environ=None):
+ app_mixin = MixinWithInstanceVariables()
app_mixin.csrf_checks = csrf_checks
if extra_environ:
app_mixin.extra_environ = extra_environ
@@ -30,4 +41,3 @@
return app_mixin.app
yield factory
- app_mixin._unpatch_settings()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest.egg-info/PKG-INFO
new/django-webtest-1.9.4/django_webtest.egg-info/PKG-INFO
--- old/django-webtest-1.9.2/django_webtest.egg-info/PKG-INFO 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest.egg-info/PKG-INFO 2018-10-27
10:58:09.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: django-webtest
-Version: 1.9.2
+Version: 1.9.4
Summary: Instant integration of Ian Bicking's WebTest
(http://docs.pylonsproject.org/projects/webtest/) with django's testing
framework.
Home-page: https://github.com/django-webtest/django-webtest
Author: Mikhail Korobov
@@ -63,11 +63,14 @@
(``django_webtest.WebTest``) that creates ``webtest.TestApp`` around
django wsgi interface and makes it available in tests as ``self.app``.
- It also features optional ``user`` argument for ``self.app.get`` and
- ``self.app.post`` methods to help making authorized requests. This
argument
+ It also features an optional ``user`` argument for ``self.app.get``,
+ ``self.app.post``, etc. to help making authorized requests. This
argument
should be a django.contrib.auth.models.User instance or a string with
user's
``username`` for the user who is supposed to be logged in. To log out
again,
- call ``self.app.reset``, clearing all cookies.
+ call ``self.app.reset``, clearing all cookies. To make a bunch of
calls
+ with the same user, call ``app.set_user(user)`` before your requests;
if
+ you want to disable that user, call ``app.get(..., user=None)`` for one
+ request or ``app.set_user(None)`` to unset the user for all following
calls.
For 500 errors original traceback is shown instead of usual html result
from handler500.
@@ -105,6 +108,7 @@
class MyTestCase(WebTest):
csrf_checks = False
+
def test_post(self)
self.app.post('/')
@@ -180,6 +184,32 @@
CHANGES
=======
+ 1.9.4 (2018-10-27)
+ ------------------
+
+ - py34 and Django 1.8 are no longer tested (but may works)
+
+ - allow to use positionnal args; fixed #89
+
+ - remove deprecated pytest.yield_fixture functions. use pytest.fixture
instead;
+ fixed #88
+
+ - Don't add duplicate WebtestUserMiddleware to the list of middlewares
in
+ WebTestMixin. fixed #87
+
+ - restore MIDDLEWARE_CLASSES support; fixed #84
+
+ 1.9.3 (2018-05-03)
+ ------------------
+
+ - Passing `user=None` to get/post/etc. methods will clear a user
+ previously set with `set_user` instead of doing nothing.
+
+ - Avoid sharing settings between tests in pytest plugin
+
+ - Fix middleware settings name used
+
+
1.9.2 (2017-05-17)
------------------
@@ -440,12 +470,11 @@
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest.egg-info/requires.txt
new/django-webtest-1.9.4/django_webtest.egg-info/requires.txt
--- old/django-webtest-1.9.2/django_webtest.egg-info/requires.txt
2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest.egg-info/requires.txt
2018-10-27 10:58:09.000000000 +0200
@@ -1 +1 @@
-webtest >= 1.3.3
+webtest>=1.3.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest_tests/settings.py
new/django-webtest-1.9.4/django_webtest_tests/settings.py
--- old/django-webtest-1.9.2/django_webtest_tests/settings.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest_tests/settings.py 2018-10-27
10:58:09.000000000 +0200
@@ -1,29 +1,21 @@
-# Django settings for django_webtest_tests project.
-import os, sys
+import os
+import sys
import django
+
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
join = lambda p: os.path.abspath(os.path.join(PROJECT_ROOT, p))
+# TODO configure pytest testpaths instead of doing this
sys.path.insert(0, join('..'))
-
-DEBUG = True
-TEMPLATE_DEBUG = DEBUG
-
-ADMINS = (
- # ('Your Name', '[email protected]'),
-)
-
-MANAGERS = ADMINS
-
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2',
'postgresql', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': join('db.sqlite'), # Or path to database
file if using sqlite3.
- 'USER': '', # Not used with sqlite3.
- 'PASSWORD': '', # Not used with sqlite3.
- 'HOST': '', # Set to empty string for localhost.
Not used with sqlite3.
- 'PORT': '', # Set to empty string for default.
Not used with sqlite3.
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': join('db.sqlite'),
+ 'USER': '',
+ 'PASSWORD': '',
+ 'HOST': '',
+ 'PORT': '',
}
}
@@ -31,49 +23,30 @@
DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql_psycopg2'
DATABASES['default']['NAME'] = 'django_webtest_tests'
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# On Unix systems, a value of None will cause Django to use the same
-# timezone as the operating system.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'America/Chicago'
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = 'en-us'
SITE_ID = 1
+ROOT_URLCONF = 'urls'
+SECRET_KEY = '5mcs97ar-(nnxhfkx0%^+0^sr!e(ax=x$2-!8dqy25ff-l1*a='
+DEBUG = False
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
USE_I18N = True
-
-# If you set this to False, Django will not format dates, numbers and
-# calendars according to the current locale
USE_L10N = True
+TIME_ZONE = 'America/Chicago'
+LANGUAGE_CODE = 'en-us'
-# Absolute path to the directory that holds media.
-# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = join('media')
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash if there is a path component (optional in other cases).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = '/media/'
-
STATIC_URL = '/static/'
+LOGIN_REDIRECT_URL = '/template/index.html'
-# Make this unique, and don't share it with anybody.
-SECRET_KEY = '5mcs97ar-(nnxhfkx0%^+0^sr!e(ax=x$2-!8dqy25ff-l1*a='
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [ ],
+ 'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
+ 'debug': DEBUG,
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
@@ -87,31 +60,33 @@
},
]
-# List of callables that know how to import templates from various sources.
-# left here for compatibility with django < 1.8
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
-# 'django.template.loaders.eggs.Loader',
-)
-TEMPLATE_DIRS = (
- join('templates'),
-)
+if django.VERSION < (1, 10):
+ TEMPLATE_DEBUG = DEBUG
-MIDDLEWARE_CLASSES = (
- 'django.middleware.common.CommonMiddleware',
+ TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+ )
+
+ TEMPLATE_DIRS = (
+ join('templates'),
+ )
+
+
+MIDDLEWARE = (
'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'testapp_tests.middleware.UserMiddleware',
)
-if django.VERSION >= (1, 10):
- MIDDLEWARE = MIDDLEWARE_CLASSES
+if django.VERSION < (1, 10):
+ MIDDLEWARE_CLASSES = MIDDLEWARE
+ del MIDDLEWARE
-ROOT_URLCONF = 'urls'
INSTALLED_APPS = (
'django.contrib.auth',
@@ -119,11 +94,7 @@
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
- # Uncomment the next line to enable the admin:
- # 'django.contrib.admin',
'django_webtest',
'django_webtest_tests',
'django_webtest_tests.testapp_tests',
)
-
-LOGIN_REDIRECT_URL = '/template/index.html'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest_tests/templates/index.html
new/django-webtest-1.9.4/django_webtest_tests/templates/index.html
--- old/django-webtest-1.9.2/django_webtest_tests/templates/index.html
2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest_tests/templates/index.html
2018-10-27 10:58:09.000000000 +0200
@@ -1,6 +1,8 @@
<!DOCTYPE html>
<h1>Hello :)</h1>
+<p>User: {{ user }}</p>
+
{% if bar %}
<ul>
{% for bar in foo %}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest_tests/testapp_tests/tests.py
new/django-webtest-1.9.4/django_webtest_tests/testapp_tests/tests.py
--- old/django-webtest-1.9.2/django_webtest_tests/testapp_tests/tests.py
2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest_tests/testapp_tests/tests.py
2018-10-27 10:58:09.000000000 +0200
@@ -1,11 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import
-from webtest import AppError, TestApp
+
import django
-from django_webtest import WebTest
from django.contrib.auth.models import User
-from django.core.urlresolvers import reverse
+try:
+ from django.urls import reverse
+except ImportError:
+ from django.core.urlresolvers import reverse
+from django.test.testcases import override_settings
+from unittest import skipIf
+
+
+from webtest import AppError, TestApp
+
+from django_webtest import WebTest
+from django_webtest.compat import is_authenticated, is_anonymous
+
class MethodsTest(WebTest):
@@ -78,23 +89,26 @@
self.assertMethodWorks(self.app.options, 'OPTIONS')
def test_get_auto_follow_default(self):
- response = self.app.get(reverse('remove-prefix-redirect',
args=('template/index.html',)))
+ response = self.app.get(reverse('remove-prefix-redirect',
+ args=('template/index.html',)))
self.assertEqual(response.status_code, 302)
def test_get_auto_follow_true(self):
- response = self.app.get(reverse('remove-prefix-redirect',
args=('template/index.html',)),
+ response = self.app.get(reverse('remove-prefix-redirect',
+ args=('template/index.html',)),
auto_follow=True)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Hello')
def test_get_auto_follow_and_expect_errors(self):
- response = self.app.get(reverse('remove-prefix-redirect',
args=('some-404/',)),
+ response = self.app.get(reverse('remove-prefix-redirect',
+ args=('some-404/',)),
auto_follow=True, expect_errors=True)
self.assertEqual(response.status_code, 404)
def test_get_with_positional_args(self):
- with self.assertRaises(TypeError):
- self.app.get('/', {})
+ response = self.app.get('/', {})
+ self.assertEqual(response.status_code, 200)
class PostRequestTest(WebTest):
@@ -175,7 +189,7 @@
def assertCanLogin(self, user):
response = self.app.get('/template/index.html', user=user)
res_user = response.context['user']
- assert res_user.is_authenticated()
+ assert is_authenticated(res_user)
if isinstance(user, User):
self.assertEqual(res_user, user)
@@ -188,7 +202,7 @@
def test_not_logged_in(self):
response = self.app.get('/template/index.html')
user = response.context['user']
- assert not user.is_authenticated()
+ assert not is_authenticated(user)
def test_logged_using_username(self):
self.assertCanLogin('foo')
@@ -253,7 +267,7 @@
response = self.app.get('/template/index.html',
user=custom_user)
user = response.context['user']
- assert user.is_authenticated()
+ assert is_authenticated(user)
self.assertEqual(user, custom_user)
def test_normal_user(self):
@@ -268,15 +282,43 @@
def test_set_user(self):
self.app.set_user(self.user.username)
environ = self.app.extra_environ
- self.assertTrue(environ['WEBTEST_USER'] == self.user.username)
+ self.assertEqual(environ['WEBTEST_USER'], self.user.username)
resp = self.app.get('/template/index.html')
+
environ = resp.request.environ
- self.assertTrue(environ['WEBTEST_USER'] == self.user.username)
+ self.assertEqual(environ['WEBTEST_USER'], self.user.username)
+ resp.mustcontain('User: {}'.format(self.user.username))
- self.app.set_user()
+ def test_set_user_reset(self):
+ self.app.set_user(self.user.username)
+ self.app.set_user(None)
environ = self.app.extra_environ
- self.assertTrue('WEBTEST_USER' not in environ)
+ self.assertNotIn('WEBTEST_USER', environ)
+
+ resp = self.app.get('/template/index.html')
+
+ environ = resp.request.environ
+ self.assertNotIn('WEBTEST_USER', environ)
+ resp.mustcontain('User: AnonymousUser')
+
+ def test_user_param(self):
+ resp = self.app.get('/template/index.html', user='bob_morane')
+
+ self.assertEqual(resp.request.environ['WEBTEST_USER'], 'bob_morane')
+
+ resp.mustcontain('User: bob_morane')
+
+ def test_user_param_reset(self):
+ self.app.set_user(self.user.username)
+ resp = self.app.get('/template/index.html', user=None)
+
+ # this request had no user
+ self.assertEqual(resp.request.environ['WEBTEST_USER'], '')
+ resp.mustcontain('User: AnonymousUser')
+ # app object is unchanged
+ self.assertEqual(self.app.extra_environ['WEBTEST_USER'],
+ self.user.username)
class EnvironTest(BaseAuthTest):
@@ -291,7 +333,7 @@
resp2 = self.app.get('/template/index.html')
environ = resp2.request.environ
- self.assertTrue('WEBTEST_USER' not in environ)
+ self.assertNotIn('WEBTEST_USER', environ)
self.assertEqual(environ['REMOTE_ADDR'], '127.0.0.2')
resp3 = self.app.get('/template/index.html',
@@ -313,7 +355,7 @@
# cookies were dropped
page2 = self.app.get('/template/form.html')
- self.assertTrue(page2.context['user'].is_anonymous())
+ self.assertTrue(is_anonymous(page2.context['user']))
# but cookies are still there while browsing from stored page
page1_1 = page1.click('Login')
@@ -371,7 +413,8 @@
def test_no_auth(self):
from django.conf import settings
- assert 'django_webtest.middleware.WebtestUserMiddleware' not in
settings.MIDDLEWARE_CLASSES
+ middleware = getattr(settings, 'MIDDLEWARE', None) or
settings.MIDDLEWARE_CLASSES
+ assert 'django_webtest.middleware.WebtestUserMiddleware' not in
middleware
assert 'django_webtest.backends.WebtestUserBackend' not in
settings.AUTHENTICATION_BACKENDS
@@ -394,7 +437,7 @@
self.assertEqual({}, self.app.session)
def test_session_not_empty(self):
- response = self.app.get(reverse('set_session'))
+ self.app.get(reverse('set_session'))
self.assertEqual('foo', self.app.session['test'])
@@ -415,3 +458,26 @@
self.app.set_cookie(str('test_cookie'), str('cookie monster!'))
rsp = self.app.get(reverse('cookie_test'))
self.assertContains(rsp, 'cookie monster!')
+
+
+@skipIf(django.VERSION < (1, 10), 'MIDDLEWARE is added in Django 1.10')
+@override_settings(MIDDLEWARE=[])
+class MiddlewareTest(WebTest):
+
+ def test_middleware_setting_name(self):
+ self.assertEqual(
+ self.middleware_setting_name,
+ 'MIDDLEWARE'
+ )
+
+
+@skipIf(django.VERSION < (1, 10) or django.VERSION >= (2, 0),
+ 'MIDDLEWARE is added in Django 1.10')
+@override_settings(MIDDLEWARE=None, MIDDLEWARE_CLASSES=[])
+class MiddlewareClassesTest(WebTest):
+
+ def test_middleware_setting_name(self):
+ self.assertEqual(
+ self.middleware_setting_name,
+ 'MIDDLEWARE_CLASSES'
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-webtest-1.9.2/django_webtest_tests/tox2travis.py
new/django-webtest-1.9.4/django_webtest_tests/tox2travis.py
--- old/django-webtest-1.9.2/django_webtest_tests/tox2travis.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest_tests/tox2travis.py 2018-10-27
10:58:09.000000000 +0200
@@ -2,9 +2,10 @@
TRAVIS_CONF = '''
language: python
-python: 3.5 # this is needed to get travis to have python3.5 as well
-sudo: false
+cache:
+ directories:
+ - $HOME/.cache/pip
addons:
postgresql: "9.3"
@@ -17,11 +18,13 @@
- pip install tox
script:
- tox
-env:
+matrix:
+ include:
'''
if __name__ == '__main__':
- import subprocess, sys
+ import subprocess
+ import sys
p = subprocess.check_output('tox -l', shell=True)
if sys.version_info.major == 3:
p = p.decode('utf-8')
@@ -30,4 +33,17 @@
for env in p.split('\n'):
env = env.strip()
if env and env not in ('travis',):
- fd.write(' - TOXENV={}\n'.format(env))
+ dist = None
+ if env.startswith('pypy'):
+ py = 'pypy'
+ else:
+ py = '{0}.{1}'.format(env[2], env[3])
+ if int(env[2] + env[3]) > 36:
+ # looks like psql dos not work on xenial... skip 3.7
+ # for now
+ continue
+ dist = 'xenial'
+ fd.write(' - python: "{}"\n'.format(py))
+ fd.write(' env: TOXENV={}\n'.format(env))
+ if dist is not None:
+ fd.write(' dist: {}\n'.format(dist))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/django_webtest_tests/urls.py
new/django-webtest-1.9.4/django_webtest_tests/urls.py
--- old/django-webtest-1.9.2/django_webtest_tests/urls.py 2017-05-17
10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/django_webtest_tests/urls.py 2018-10-27
10:58:09.000000000 +0200
@@ -1,40 +1,47 @@
-
-# prevent DeprecationWarning for more recent django versions
try:
from django.conf.urls import url
except ImportError:
- from django.conf.urls.defaults import patterns, url, handler404, handler500
+ from django.conf.urls.defaults import url
from django.http import HttpResponse
from django.shortcuts import render
-from django.contrib.auth.views import login
from testapp_tests.views import check_password, search, set_session, \
- protected, redirect_to_protected, remove_prefix_redirect, cookie_test \
+ protected, redirect_to_protected, remove_prefix_redirect, cookie_test
+
+try:
+ from django.contrib.auth.views import login
+except ImportError:
+ # django 2+
+ from django.contrib.auth.views import LoginView
+ login = LoginView.as_view()
-# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-# admin.autodiscover()
def simple_method_test(request):
return HttpResponse(str(request.method))
+
def simple_template_render(request, template_name):
return render(request, template_name, {
+ 'user': request.user,
'foo': ('a', 'b', 'c'),
'bar': True,
'spam': None,
})
+
urlpatterns = (
url(r'^$', simple_method_test, name='simple-method-test'),
- url(r'^template/(.*)$', simple_template_render,
name='simple-template-test'),
+ url(r'^template/(.*)$', simple_template_render,
+ name='simple-template-test'),
url(r'^check-password/$', check_password, name='check_password'),
url(r'^search/$', search, name='search'),
url(r'^login/$', login, name='auth_login'),
url(r'^set-session/$', set_session, name='set_session'),
url(r'^protected/$', protected, name='protected'),
- url(r'^redirect-to-protected/$', redirect_to_protected,
name='redirect-to-protected'),
- url(r'^remove-prefix-redirect/(.*)/$', remove_prefix_redirect,
name='remove-prefix-redirect'),
+ url(r'^redirect-to-protected/$',
+ redirect_to_protected, name='redirect-to-protected'),
+ url(r'^remove-prefix-redirect/(.*)/$',
+ remove_prefix_redirect, name='remove-prefix-redirect'),
url(r'^cookie-test/$', cookie_test, name='cookie_test'),
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/setup.cfg
new/django-webtest-1.9.4/setup.cfg
--- old/django-webtest-1.9.2/setup.cfg 2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/setup.cfg 2018-10-27 10:58:09.000000000 +0200
@@ -4,5 +4,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/setup.py
new/django-webtest-1.9.4/setup.py
--- old/django-webtest-1.9.2/setup.py 2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/setup.py 2018-10-27 10:58:09.000000000 +0200
@@ -4,7 +4,7 @@
from setuptools import setup
-version = '1.9.2'
+version = '1.9.4'
def _read(name):
@@ -52,12 +52,11 @@
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.2',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries :: Python Modules',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-webtest-1.9.2/tox.ini
new/django-webtest-1.9.4/tox.ini
--- old/django-webtest-1.9.2/tox.ini 2017-05-17 10:52:10.000000000 +0200
+++ new/django-webtest-1.9.4/tox.ini 2018-10-27 10:58:09.000000000 +0200
@@ -2,18 +2,18 @@
skip_missing_interpreters = true
envlist =
pypy-django19-std,
- {py27,py34}-django{18,19,110,111}-{std,clocale,postgres},
- py35-django{18,19,110,111}-{std,clocale,postgres}
+ py27-django{19,110,111}-{std,clocale,postgres},
+ {py35,py36,py37}-django{19,110,111,20}-{std,clocale,postgres}
[testenv]
deps=
pytest
pytest-django
postgres: psycopg2
- django18: django >=1.8, < 1.9
django19: django >=1.9, < 1.9.9
django110: django >=1.10, < 1.11
django111: django >=1.11, < 2.0
+ django20: django ~= 2.0
setenv=
clocale: LC_ALL=C
postgres: USE_POSTGRES=True