Skip to content

Commit b8169d9

Browse files
pandafynemesifier
authored andcommitted
[deps] Added support for Django 4.1.0 and Django 4.2.0
- Dropped support for Python 3.7 - Dropped support for Django 4.0.0 - Bumped django-reversion~=5.0.4 - Bumped django-taggit~=4.0.0 - Bumped paramiko[ed25519]~=3.2.0 - Bumped django-import-export~=3.2.0 - [tests] Fixed selenium tests - [fix] Fixed CSS for jsonschema UI - [fix] Fixed flaky test_create_new_device test
1 parent 6adafe3 commit b8169d9

File tree

36 files changed

+110
-74
lines changed

36 files changed

+110
-74
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
ports:
2323
- 6379:6379
2424
postgres:
25-
image: mdillon/postgis:11-alpine
25+
image: postgis/postgis:13-3.3-alpine
2626
env:
2727
POSTGRES_PASSWORD: openwisp2
2828
POSTGRES_USER: openwisp2
@@ -39,10 +39,8 @@ jobs:
3939
- "3.10"
4040
django-version:
4141
- django~=3.2.0
42-
- django~=4.0.0
43-
include:
44-
- django-version: django~=3.2.0
45-
python-version: 3.7
42+
- django~=4.1.0
43+
- django~=4.2.0
4644

4745
steps:
4846
- uses: actions/checkout@v2
@@ -67,13 +65,13 @@ jobs:
6765
- name: Upgrade python system packages
6866
run: pip install -U pip wheel setuptools
6967

70-
- name: Install openwisp-controller
71-
run: |
72-
pip install -e .
73-
7468
- name: Install test dependencies
7569
run: |
7670
pip install -U -r requirements-test.txt
71+
72+
- name: Install openwisp-controller
73+
run: |
74+
pip install -U -e .
7775
pip install ${{ matrix.django-version }}
7876
7977
- name: QA checks
@@ -82,9 +80,11 @@ jobs:
8280
- name: Tests
8381
run: |
8482
coverage run runtests.py --parallel
83+
# the following command runs tests with Postgres/PostGIS but
84+
# only for specific test cases which are tagged with "db_tests"
8585
POSTGRESQL=1 coverage run runtests.py --parallel --keepdb
8686
coverage combine
87-
# SAMPLE tests
87+
# tests the extension capability
8888
SAMPLE_APP=1 ./runtests.py --keepdb
8989
env:
9090
SELENIUM_HEADLESS: 1

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ services:
2121
entrypoint: redis-server --appendonly yes
2222

2323
postgres:
24-
image: mdillon/postgis:11-alpine
24+
image: postgis/postgis:13-3.3-alpine
2525
environment:
2626
POSTGRES_PASSWORD: openwisp2
2727
POSTGRES_USER: openwisp2
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp_controller.config.apps.ConfigConfig'

openwisp_controller/config/migrations/0030_django_taggit_update.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class Migration(migrations.Migration):
3535
migrations.AlterField(
3636
model_name='templatetag',
3737
name='slug',
38-
field=models.SlugField(max_length=100, unique=True, verbose_name='slug'),
38+
field=models.SlugField(
39+
allow_unicode=True, max_length=100, unique=True, verbose_name='slug'
40+
),
3941
),
4042
]

openwisp_controller/config/static/config/css/lib/advanced-mode.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,9 @@ table.jsoneditor-search button.jsoneditor-previous:hover {
857857
#main .property-selector .form-row {
858858
padding: 5px 0 6px 10px !important;
859859
}
860+
#main .property-selector {
861+
text-align: left;
862+
}
860863
@media (max-width: 768px){
861864
.jsoneditor-menu #netjsonconfig-hint-advancedmode{
862865
display: none;

openwisp_controller/config/static/config/js/widget.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ JSONEditor.defaults.themes.django = JSONEditor.AbstractTheme.extend({
543543
},
544544
getCheckbox: function () {
545545
var el = this.getFormInputField('checkbox');
546+
el.className = null;
546547
el.style.display = 'inline-block';
547548
el.style.width = 'auto';
548549
return el;

openwisp_controller/config/tests/test_selenium.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
2+
from django.test import tag
23
from django.urls.base import reverse
34
from selenium.common.exceptions import (
45
StaleElementReferenceException,
@@ -16,6 +17,7 @@
1617
from .utils import CreateConfigTemplateMixin
1718

1819

20+
@tag('selenium_tests')
1921
class TestDeviceAdmin(
2022
TestOrganizationMixin,
2123
CreateConfigTemplateMixin,
@@ -84,7 +86,7 @@ def test_create_new_device(self):
8486

8587
try:
8688
WebDriverWait(self.web_driver, 2).until(
87-
EC.element_to_be_clickable(
89+
EC.presence_of_element_located(
8890
(By.XPATH, f'//*[@value="{default_template.id}"]')
8991
)
9092
)

openwisp_controller/config/tests/test_template.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from openwisp_users.tests.utils import TestOrganizationMixin
1313
from openwisp_utils.tests import catch_signal
1414

15+
from ...tests.utils import TransactionTestMixin
1516
from .. import settings as app_settings
1617
from ..signals import config_modified, config_status_changed
1718
from ..tasks import logger as task_logger
@@ -504,6 +505,7 @@ def test_required_vpn_template_corner_case(self):
504505

505506

506507
class TestTemplateTransaction(
508+
TransactionTestMixin,
507509
TestOrganizationMixin,
508510
CreateConfigTemplateMixin,
509511
TestVpnX509Mixin,
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp_controller.connection.apps.ConnectionConfig'

openwisp_controller/connection/tests/test_models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from openwisp_utils.tests import capture_any_output, catch_signal
1313

14+
from ...tests.utils import TransactionTestMixin
1415
from .. import settings as app_settings
1516
from ..apps import _TASK_NAME
1617
from ..commands import (
@@ -835,7 +836,7 @@ def test_command_multiple_connections(self, connect_mocked):
835836
self.assertIn(command.connection, [dc1, dc2])
836837

837838

838-
class TestModelsTransaction(BaseTestModels, TransactionTestCase):
839+
class TestModelsTransaction(TransactionTestMixin, BaseTestModels, TransactionTestCase):
839840
def _prepare_conf_object(self, organization=None):
840841
if not organization:
841842
organization = self._create_org(name='org1')

openwisp_controller/geo/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp_controller.geo.apps.GeoConfig'

openwisp_controller/geo/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,6 @@ def register_menu_groups(self):
114114
'icon': 'ow-geo',
115115
},
116116
)
117+
118+
119+
del LociConfig

openwisp_controller/pki/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp_controller.pki.apps.PkiConfig'

openwisp_controller/pki/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ def register_menu_groups(self):
4141
'icon': 'ow-cer-group',
4242
},
4343
)
44+
45+
46+
del DjangoX509Config
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp_controller.subnet_division.apps.SubnetDivisionConfig'

openwisp_controller/subnet_division/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class SubnetAdmin(BaseSubnetAdmin):
5858
VpnFilter,
5959
DeviceFilter,
6060
]
61-
inlines = [SubnetDivisionRuleInlineAdmin] + BaseSubnetAdmin.inlines
61+
inlines = [SubnetDivisionRuleInlineAdmin] + list(BaseSubnetAdmin.inlines)
6262
list_display = BaseSubnetAdmin.list_display
6363
list_display.insert(list_display.index('created'), 'related_device')
6464

openwisp_controller/subnet_division/tests/test_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ def test_rule_deleted(self):
330330

331331
self.assertEqual(subnet_query.count(), 0)
332332
self.assertEqual(ip_query.count(), 0)
333-
self.assertEqual(index_query.count(), 0)
333+
self.assertEqual(SubnetDivisionIndex.objects.count(), 0)
334334

335335
def test_vpnclient_deleted(self):
336336
rule = self._get_vpn_subdivision_rule()

openwisp_controller/tests/test_selenium.py

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
from unittest.mock import patch
2+
13
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
24
from django.core.management import call_command
5+
from django.test import tag
36
from django.urls.base import reverse
47
from reversion.models import Version
5-
from selenium.common.exceptions import TimeoutException, UnexpectedAlertPresentException
6-
from selenium.webdriver.common.alert import Alert
8+
from selenium.common.exceptions import TimeoutException
79
from selenium.webdriver.common.by import By
810
from selenium.webdriver.support import expected_conditions as EC
911
from selenium.webdriver.support.ui import WebDriverWait
@@ -19,6 +21,7 @@
1921
DeviceLocation = load_model('geo', 'DeviceLocation')
2022

2123

24+
@tag('selenium_tests')
2225
class TestDeviceConnectionInlineAdmin(
2326
CreateConnectionsMixin, TestGeoMixin, SeleniumTestMixin, StaticLiveServerTestCase
2427
):
@@ -31,27 +34,8 @@ def setUp(self):
3134
username=self.admin_username, password=self.admin_password
3235
)
3336

34-
def tearDown(self):
35-
# Accept unsaved changes alert to allow other tests to run
36-
try:
37-
self.web_driver.refresh()
38-
except UnexpectedAlertPresentException:
39-
alert = Alert(self.web_driver)
40-
alert.accept()
41-
else:
42-
try:
43-
WebDriverWait(self.web_driver, 1).until(EC.alert_is_present())
44-
except TimeoutException:
45-
pass
46-
else:
47-
alert = Alert(self.web_driver)
48-
alert.accept()
49-
self.web_driver.refresh()
50-
WebDriverWait(self.web_driver, 2).until(
51-
EC.visibility_of_element_located((By.XPATH, '//*[@id="site-name"]'))
52-
)
53-
54-
def test_restoring_deleted_device(self):
37+
@patch('reversion.models.logger.warning')
38+
def test_restoring_deleted_device(self, *args):
5539
org = self._get_org()
5640
self._create_credentials(auto_add=True, organization=org)
5741
device = self._create_config(organization=org).device

openwisp_controller/tests/utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import django
12
from django.contrib.auth import get_user_model
3+
from django.db import connections
4+
from django.db.utils import DEFAULT_DB_ALIAS
5+
from django.test.testcases import _AssertNumQueriesContext
26
from django.urls import reverse
37

48
from openwisp_users.tests.utils import TestMultitenantAdminMixin
@@ -16,3 +20,32 @@ def _test_changelist_recover_deleted(self, app_label, model_label):
1620

1721
def _login(self, username='admin', password='tester'):
1822
self.client.force_login(user_model.objects.get(username=username))
23+
24+
25+
class _ManagementTransactionNumQueriesContext(_AssertNumQueriesContext):
26+
def __exit__(self, exc_type, exc_value, traceback):
27+
"""
28+
Django 4.2 introduced support for logging transaction
29+
management queries (BEGIN, COMMIT, and ROLLBACK).
30+
This method increases the number of expected database
31+
queries if COMMIT/ROLLBACK queries are found when
32+
using Django 4.2
33+
"""
34+
if exc_type is not None:
35+
return
36+
for query in self.captured_queries:
37+
if django.VERSION > (4, 2) and 'COMMIT' in query['sql']:
38+
self.num += 1
39+
super().__exit__(exc_type, exc_value, traceback)
40+
41+
42+
class TransactionTestMixin(object):
43+
def assertNumQueries(self, num, func=None, *args, using=DEFAULT_DB_ALIAS, **kwargs):
44+
conn = connections[using]
45+
46+
context = _ManagementTransactionNumQueriesContext(self, num, conn)
47+
if func is None:
48+
return context
49+
50+
with context:
51+
func(*args, **kwargs)

requirements-test.txt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
pytest~=6.0
21
pytest-django~=4.5.2
3-
pytest-asyncio~=0.14.0
4-
pytest-cov~=2.10.0
2+
pytest-asyncio~=0.21.0
3+
pytest-cov~=4.1.0
54
openwisp-utils[qa,selenium] @ https://github.com/openwisp/openwisp-utils/tarball/master
6-
redis~=4.5.4
75
channels_redis~=4.1.0
86
django_redis~=5.2.0
97
mock-ssh-server~=0.9.1
10-
responses~=0.12.1
11-
psycopg2-binary~=2.8.0
8+
responses~=0.23.1
9+
psycopg2-binary~=2.9.6

requirements.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
django-sortedm2m~=3.1.1
2-
django-reversion~=4.0.1
3-
django-taggit~=2.1.0
2+
django-reversion~=5.0.4
3+
django-taggit~=4.0.0
44
netjsonconfig~=1.0.1
55
django-x509 @ https://github.com/openwisp/django-x509/tarball/master
66
django-loci @ https://github.com/openwisp/django-loci/tarball/master
77
django-flat-json-widget @ https://github.com/openwisp/django-flat-json-widget/tarball/master
88
openwisp-users @ https://github.com/openwisp/openwisp-users/tarball/master
9+
openwisp-utils[celery] @ https://github.com/openwisp/openwisp-utils/tarball/master
910
openwisp-notifications @ https://github.com/openwisp/openwisp-notifications/tarball/master
1011
openwisp-ipam @ https://github.com/openwisp/openwisp-ipam/tarball/master
1112
djangorestframework-gis~=0.18.0
12-
paramiko[ed25519]~=2.10.3
13+
paramiko[ed25519]~=3.2.0
1314
scp~=0.14.2
14-
celery~=5.2.3
15-
django-cache-memoize~=0.1
15+
django-cache-memoize~=0.1.0
1616
shortuuid~=1.0.1
1717
netaddr~=0.8.0
18-
django-import-export~=2.8.0
18+
django-import-export~=3.2.0

runtests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
if os.environ.get('POSTGRESQL', False):
2626
args.extend(['--tag', 'db_tests'])
27+
args.extend(['--tag', 'selenium_tests'])
28+
else:
29+
args.extend(['--exclude-tag', 'selenium_tests'])
2730

2831
execute_from_command_line(args)
2932

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_config.apps.SampleConfigConfig'

tests/openwisp2/sample_config/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
class SampleConfigConfig(ConfigConfig):
55
name = 'openwisp2.sample_config'
66
label = 'sample_config'
7+
8+
9+
del ConfigConfig

tests/openwisp2/sample_config/migrations/0001_initial.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,12 @@ class Migration(migrations.Migration):
191191
),
192192
(
193193
'slug',
194-
models.SlugField(max_length=100, unique=True, verbose_name='slug'),
194+
models.SlugField(
195+
allow_unicode=True,
196+
max_length=100,
197+
unique=True,
198+
verbose_name='slug',
199+
),
195200
),
196201
('details', models.CharField(blank=True, max_length=64, null=True)),
197202
],
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_connection.apps.SampleConnectionConfig'

tests/openwisp2/sample_connection/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
class SampleConnectionConfig(ConnectionConfig):
55
name = 'openwisp2.sample_connection'
66
label = 'sample_connection'
7+
8+
9+
del ConnectionConfig
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_geo.apps.SampleGeoConfig'

tests/openwisp2/sample_geo/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
class SampleGeoConfig(GeoConfig):
55
name = 'openwisp2.sample_geo'
66
label = 'sample_geo'
7+
8+
9+
del GeoConfig
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_pki.apps.SamplePkiConfig'

tests/openwisp2/sample_pki/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
class SamplePkiConfig(PkiConfig):
55
name = 'openwisp2.sample_pki'
66
label = 'sample_pki'
7+
8+
9+
del PkiConfig
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_subnet_division.apps.SampleSubnetDivisionConfig'

tests/openwisp2/sample_subnet_division/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
class SampleSubnetDivisionConfig(SubnetDivisionConfig):
55
name = 'openwisp2.sample_subnet_division'
66
label = 'sample_subnet_division'
7+
8+
9+
del SubnetDivisionConfig
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
default_app_config = 'openwisp2.sample_users.apps.SampleUsersConfig'

0 commit comments

Comments
 (0)