Django 2.0 support and fix lower-constraints

Replace django.core.urlresolves with django.urls

(In Django 2.0) The django.core.urlresolvers module is removed
in favor of its new location, django.urls.
It was deprecated in Django 1.10:
https://docs.djangoproject.com/en/2.0/releases/1.10/#id3

To test the dashboard with python3 and Django 1.11,
python3-django111 job is added to tox.ini and a corresponding
entry is added to .zuul.yaml.

requirements.txt is also updated not to include horizon dependecies.
This allows horizon plugins not to track changes in basic stuffs
like Django.

KeyError from memoized decorator occurs in watcher-dashboard python3
tests but it seems it is not specific to Django 2.0 support,
so it is not touched. Hopefully it can be fixed later.

lower-constraints job is also fixed.
- Previously install_command specifies upper-constraints.txt even for
  lower-constraints tox env. As a result, lower-constraints job actually
  tests upper-constraints.
  This commit moves -c option for upper-constraints.txt to 'deps'.
- lower-constraints.txt is updated.
- nose-exclude 0.3.0 actually does not work. 0.5.0 needs to be used.

Change-Id: Ia98e4685f217c1e932d4b68b864cd9f52c88b134
This commit is contained in:
Akihiro Motoki 2018-06-21 23:54:48 +09:00
parent f0f6cef879
commit 5a7ebe5016
15 changed files with 55 additions and 58 deletions

View File

@ -2,6 +2,8 @@
check: check:
jobs: jobs:
- openstack-tox-lower-constraints - openstack-tox-lower-constraints
- horizon-openstack-tox-python3-django111
gate: gate:
jobs: jobs:
- openstack-tox-lower-constraints - openstack-tox-lower-constraints
- horizon-openstack-tox-python3-django111

View File

@ -8,7 +8,7 @@ chardet==3.0.4
cliff==2.11.0 cliff==2.11.0
cmd2==0.8.1 cmd2==0.8.1
contextlib2==0.5.5 contextlib2==0.5.5
coverage==4.5.1 coverage==4.0
cryptography==2.1.4 cryptography==2.1.4
debtcollector==1.19.0 debtcollector==1.19.0
decorator==4.2.1 decorator==4.2.1
@ -17,7 +17,7 @@ Django==1.11.11
django-appconf==1.0.2 django-appconf==1.0.2
django-babel==0.6.2 django-babel==0.6.2
django-compressor==2.2 django-compressor==2.2
django-nose==1.4.5 django-nose==1.4.4
django-pyscss==2.0.2 django-pyscss==2.0.2
docutils==0.14 docutils==0.14
dogpile.cache==0.6.5 dogpile.cache==0.6.5
@ -28,7 +28,7 @@ fixtures==3.0.0
flake8==2.5.5 flake8==2.5.5
futurist==1.6.0 futurist==1.6.0
hacking==0.12.0 hacking==0.12.0
horizon==13.0.0 horizon==14.0.0.b1
httplib2==0.10.3 httplib2==0.10.3
idna==2.6 idna==2.6
imagesize==1.0.0 imagesize==1.0.0
@ -44,14 +44,14 @@ MarkupSafe==1.0
mccabe==0.2.1 mccabe==0.2.1
mock==2.0.0 mock==2.0.0
monotonic==1.4 monotonic==1.4
mox3==0.25.0 mox3==0.20.0
msgpack==0.5.6 msgpack==0.5.6
munch==2.2.0 munch==2.2.0
netaddr==0.7.19 netaddr==0.7.19
netifaces==0.10.6 netifaces==0.10.6
nose==1.3.7 nose==1.3.7
nose-exclude==0.5.0 nose-exclude==0.5.0
openstackdocstheme==1.20.0 openstackdocstheme==1.18.1
openstacksdk==0.12.0 openstacksdk==0.12.0
os-client-config==1.29.0 os-client-config==1.29.0
os-service-types==1.2.0 os-service-types==1.2.0
@ -64,7 +64,7 @@ oslo.serialization==2.25.0
oslo.utils==3.36.0 oslo.utils==3.36.0
osprofiler==2.0.0 osprofiler==2.0.0
packaging==17.1 packaging==17.1
pbr==3.1.1 pbr==2.0.0
pep8==1.5.7 pep8==1.5.7
Pint==0.8.1 Pint==0.8.1
prettytable==0.7.2 prettytable==0.7.2
@ -82,27 +82,27 @@ python-keystoneclient==3.15.0
python-mimeparse==1.6.0 python-mimeparse==1.6.0
python-neutronclient==6.7.0 python-neutronclient==6.7.0
python-novaclient==10.1.0 python-novaclient==10.1.0
python-subunit==1.2.0 python-subunit==1.0.0
python-swiftclient==3.5.0 python-swiftclient==3.5.0
python-watcherclient==1.6.0 python-watcherclient==1.1.0
pytz==2018.3 pytz==2018.3
PyYAML==3.12 PyYAML==3.12
rcssmin==1.0.6 rcssmin==1.0.6
reno==2.7.0 reno==2.5.0
requests==2.18.4 requests==2.18.4
requestsexceptions==1.4.0 requestsexceptions==1.4.0
rfc3986==1.1.0 rfc3986==1.1.0
rjsmin==1.0.12 rjsmin==1.0.12
selenium==3.11.0 selenium==2.50.1
semantic-version==2.6.0 semantic-version==2.6.0
simplejson==3.13.2 simplejson==3.13.2
six==1.11.0 six==1.11.0
snowballstemmer==1.2.1 snowballstemmer==1.2.1
Sphinx==1.6.5 Sphinx==1.6.2
sphinxcontrib-websupport==1.0.1 sphinxcontrib-websupport==1.0.1
stevedore==1.28.0 stevedore==1.28.0
testscenarios==0.5.0 testscenarios==0.4
testtools==2.3.0 testtools==2.2.0
traceback2==1.4.0 traceback2==1.4.0
unittest2==1.1.0 unittest2==1.1.0
urllib3==1.22 urllib3==1.22
@ -137,4 +137,4 @@ XStatic-smart-table==1.4.13.2
XStatic-Spin==1.2.5.2 XStatic-Spin==1.2.5.2
XStatic-term.js==0.0.7.0 XStatic-term.js==0.0.7.0
XStatic-tv4==1.2.7.0 XStatic-tv4==1.2.7.0
xvfbwrapper==0.2.9 xvfbwrapper==0.1.3

View File

@ -3,14 +3,8 @@
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0
# Horizon Core Requirements
Django<2.0,>=1.11 # BSD horizon>=14.0.0.0b1 # Apache-2.0
django-compressor>=2.0 # MIT
httplib2>=0.9.1 # MIT
python-keystoneclient>=3.8.0 # Apache-2.0
PyYAML>=3.12 # MIT PyYAML>=3.12 # MIT
horizon>=13.0.0 # Apache-2.0
# Watcher-specific requirements
python-watcherclient>=1.1.0 # Apache-2.0 python-watcherclient>=1.1.0 # Apache-2.0

View File

@ -8,7 +8,7 @@ coverage!=4.4,>=4.0 # Apache-2.0
django-nose>=1.4.4 # BSD django-nose>=1.4.4 # BSD
mock>=2.0.0 # BSD mock>=2.0.0 # BSD
mox3>=0.20.0 # Apache-2.0 mox3>=0.20.0 # Apache-2.0
nose-exclude>=0.3.0 # LGPL nose-exclude>=0.5.0 # LGPL
python-subunit>=1.0.0 # Apache-2.0/BSD python-subunit>=1.0.0 # Apache-2.0/BSD
selenium>=2.50.1 # Apache-2.0 selenium>=2.50.1 # Apache-2.0
testscenarios>=0.4 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD

15
tox.ini
View File

@ -5,7 +5,6 @@ skipsdist = True
[testenv] [testenv]
usedevelop = True usedevelop = True
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
NOSE_WITH_OPENSTACK=1 NOSE_WITH_OPENSTACK=1
NOSE_OPENSTACK_COLOR=1 NOSE_OPENSTACK_COLOR=1
@ -19,7 +18,9 @@ setenv = VIRTUAL_ENV={envdir}
whitelist_externals = /bin/bash whitelist_externals = /bin/bash
rm rm
find find
deps = -r{toxinidir}/requirements.txt deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
commands = commands =
rm -f .testrepository/times.dbm rm -f .testrepository/times.dbm
@ -35,11 +36,11 @@ commands = flake8
[testenv:venv] [testenv:venv]
commands = {posargs} commands = {posargs}
# Django-1.8 is LTS [testenv:py3-dj111]
[testenv:py27dj18] basepython = python3
basepython = python2.7 commands =
commands = pip install django>=1.8,<1.9 pip install django>=1.11,<2
/bin/bash run_tests.sh -N --no-pep8 {posargs} {[testenv]commands}
[testenv:py27integration] [testenv:py27integration]
basepython = python2.7 basepython = python2.7

View File

@ -15,8 +15,8 @@
import logging import logging
from django.core import urlresolvers
from django.template.defaultfilters import title # noqa from django.template.defaultfilters import title # noqa
from django import urls
from django.utils.translation import pgettext_lazy from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy from django.utils.translation import ungettext_lazy
@ -139,10 +139,10 @@ def format_global_efficacy(action_plan):
def get_audit_link(datum): def get_audit_link(datum):
try: try:
return urlresolvers.reverse( return urls.reverse(
"horizon:admin:audits:detail", "horizon:admin:audits:detail",
kwargs={"audit_uuid": getattr(datum, "audit_uuid", None)}) kwargs={"audit_uuid": getattr(datum, "audit_uuid", None)})
except urlresolvers.NoReverseMatch: except urls.NoReverseMatch:
return None return None

View File

@ -15,8 +15,8 @@
import logging import logging
from django.core import urlresolvers
from django.template.defaultfilters import title # noqa from django.template.defaultfilters import title # noqa
from django import urls
from django.utils.translation import pgettext_lazy from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import horizon.exceptions import horizon.exceptions
@ -63,11 +63,11 @@ class ActionsFilterAction(horizon.tables.FilterAction):
def get_action_plan_link(datum): def get_action_plan_link(datum):
try: try:
return urlresolvers.reverse( return urls.reverse(
"horizon:admin:action_plans:detail", "horizon:admin:action_plans:detail",
kwargs={"action_plan_uuid": getattr( kwargs={"action_plan_uuid": getattr(
datum, "action_plan_uuid", None)}) datum, "action_plan_uuid", None)})
except urlresolvers.NoReverseMatch: except urls.NoReverseMatch:
return None return None

View File

@ -19,7 +19,7 @@ Forms for starting Watcher Audit Templates.
import logging import logging
from django.core import exceptions as core_exc from django.core import exceptions as core_exc
from django.core.urlresolvers import reverse from django.urls import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from horizon import exceptions from horizon import exceptions
from horizon import forms from horizon import forms

View File

@ -13,15 +13,15 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from django.core import urlresolvers from django import urls
import mock import mock
from watcher_dashboard import api from watcher_dashboard import api
from watcher_dashboard.test import helpers as test from watcher_dashboard.test import helpers as test
INDEX_URL = urlresolvers.reverse( INDEX_URL = urls.reverse(
'horizon:admin:audit_templates:index') 'horizon:admin:audit_templates:index')
CREATE_URL = urlresolvers.reverse( CREATE_URL = urls.reverse(
'horizon:admin:audit_templates:create') 'horizon:admin:audit_templates:create')
DETAILS_VIEW = 'horizon:admin:audit_templates:detail' DETAILS_VIEW = 'horizon:admin:audit_templates:detail'
@ -83,7 +83,7 @@ class AuditTemplatesTest(test.BaseAdminViewTests):
at_id = at.uuid at_id = at.uuid
m_get.return_value = at m_get.return_value = at
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[at_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertTemplateUsed(res, self.assertTemplateUsed(res,
'infra_optim/audit_templates/details.html') 'infra_optim/audit_templates/details.html')
@ -96,7 +96,7 @@ class AuditTemplatesTest(test.BaseAdminViewTests):
at_id = at.uuid at_id = at.uuid
m_get.side_effect = self.exceptions.watcher m_get.side_effect = self.exceptions.watcher
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[at_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertRedirectsNoFollow(res, INDEX_URL) self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@ -16,7 +16,7 @@
import json import json
import logging import logging
from django.core.urlresolvers import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import horizon.exceptions import horizon.exceptions
from horizon import forms from horizon import forms

View File

@ -18,7 +18,7 @@ Forms for starting Watcher Audits.
""" """
import logging import logging
from django.core.urlresolvers import reverse from django.urls import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from horizon import exceptions from horizon import exceptions

View File

@ -13,9 +13,9 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from django.core import urlresolvers
from django import shortcuts from django import shortcuts
from django.template.defaultfilters import title # noqa from django.template.defaultfilters import title # noqa
from django import urls
from django.utils.translation import pgettext_lazy from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy from django.utils.translation import ungettext_lazy
@ -74,7 +74,7 @@ class GoToActionPlan(horizon.tables.Action):
_("Unable to retrieve action_plan information.")) _("Unable to retrieve action_plan information."))
return "javascript:void(0);" return "javascript:void(0);"
return shortcuts.redirect(urlresolvers.reverse( return shortcuts.redirect(urls.reverse(
self.url, self.url,
args=[action_plans[0].uuid])) args=[action_plans[0].uuid]))

View File

@ -15,8 +15,8 @@
import logging import logging
from django.core.urlresolvers import reverse from django.urls import reverse
from django.core.urlresolvers import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import horizon.exceptions import horizon.exceptions
from horizon import forms from horizon import forms

View File

@ -13,13 +13,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from django.core import urlresolvers from django import urls
import mock import mock
from watcher_dashboard import api from watcher_dashboard import api
from watcher_dashboard.test import helpers as test from watcher_dashboard.test import helpers as test
INDEX_URL = urlresolvers.reverse('horizon:admin:goals:index') INDEX_URL = urls.reverse('horizon:admin:goals:index')
DETAILS_VIEW = 'horizon:admin:goals:detail' DETAILS_VIEW = 'horizon:admin:goals:detail'
@ -48,7 +48,7 @@ class GoalsTest(test.BaseAdminViewTests):
goal_id = goal.uuid goal_id = goal.uuid
mock_get.return_value = goal mock_get.return_value = goal
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[goal_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[goal_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertTemplateUsed(res, 'infra_optim/goals/details.html') self.assertTemplateUsed(res, 'infra_optim/goals/details.html')
goals = res.context['goal'] goals = res.context['goal']
@ -60,6 +60,6 @@ class GoalsTest(test.BaseAdminViewTests):
at_id = at.uuid at_id = at.uuid
mock_get.side_effect = self.exceptions.watcher mock_get.side_effect = self.exceptions.watcher
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[at_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertRedirectsNoFollow(res, INDEX_URL) self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@ -13,13 +13,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from django.core import urlresolvers from django import urls
import mock import mock
from watcher_dashboard import api from watcher_dashboard import api
from watcher_dashboard.test import helpers as test from watcher_dashboard.test import helpers as test
INDEX_URL = urlresolvers.reverse( INDEX_URL = urls.reverse(
'horizon:admin:strategies:index') 'horizon:admin:strategies:index')
DETAILS_VIEW = 'horizon:admin:strategies:detail' DETAILS_VIEW = 'horizon:admin:strategies:detail'
@ -56,7 +56,7 @@ class StrategiesTest(test.BaseAdminViewTests):
at_id = at.uuid at_id = at.uuid
mock_get.return_value = at mock_get.return_value = at
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[at_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertTemplateUsed(res, self.assertTemplateUsed(res,
'infra_optim/strategies/details.html') 'infra_optim/strategies/details.html')
@ -69,6 +69,6 @@ class StrategiesTest(test.BaseAdminViewTests):
at_id = at.uuid at_id = at.uuid
mock_get.side_effect = self.exceptions.watcher mock_get.side_effect = self.exceptions.watcher
DETAILS_URL = urlresolvers.reverse(DETAILS_VIEW, args=[at_id]) DETAILS_URL = urls.reverse(DETAILS_VIEW, args=[at_id])
res = self.client.get(DETAILS_URL) res = self.client.get(DETAILS_URL)
self.assertRedirectsNoFollow(res, INDEX_URL) self.assertRedirectsNoFollow(res, INDEX_URL)