From 12bfbf8847050c7e8634db1e96ef41bcf187f873 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:24:05 -0700 Subject: [PATCH 01/14] Use importlib.metadata instead of pkg_resources --- user_sessions/__init__.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/user_sessions/__init__.py b/user_sessions/__init__.py index 862f33f..ee12b74 100644 --- a/user_sessions/__init__.py +++ b/user_sessions/__init__.py @@ -1,7 +1,12 @@ -from pkg_resources import DistributionNotFound, get_distribution - try: - __version__ = get_distribution("django-user-sessions").version -except DistributionNotFound: - # package is not installed - __version__ = None + from importlib.metadata import version +except ImportError: + from pkg_resources import DistributionNotFound, get_distribution + + try: + __version__ = get_distribution("django-user-sessions").version + except DistributionNotFound: + # package is not installed + __version__ = None +else: + __version__ = version("django-user-sessions") From d89ec98027adce729ff07ede38cdb6189f62c4ad Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:26:58 -0700 Subject: [PATCH 02/14] Ignore admin.W411 --- tests/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/settings.py b/tests/settings.py index b2b6ea7..c081b81 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -61,4 +61,4 @@ LOGIN_URL = '/admin/' LOGOUT_REDIRECT_URL = '/' -SILENCED_SYSTEM_CHECKS = ['admin.E406', 'admin.E409', 'admin.E410'] +SILENCED_SYSTEM_CHECKS = ['admin.E406', 'admin.E409', 'admin.E410', 'admin.W411'] From b6409b952497352f73b96e2fd5b6066cb87d3655 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:32:04 -0700 Subject: [PATCH 03/14] Modernize tests/settings.py --- tests/settings.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/settings.py b/tests/settings.py index c081b81..5ea39af 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,6 +1,7 @@ -import os +from pathlib import Path -BASE_DIR = os.path.dirname(__file__) +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' @@ -38,7 +39,7 @@ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ - os.path.join(BASE_DIR, 'templates'), + BASE_DIR / 'templates', ], 'APP_DIRS': True, 'OPTIONS': { @@ -55,7 +56,7 @@ }, ] -GEOIP_PATH = os.path.join(os.path.dirname(BASE_DIR), 'GeoLite2-City.mmdb') +GEOIP_PATH = BASE_DIR.parent / 'GeoLite2-City.mmdb' SESSION_ENGINE = 'user_sessions.backends.db' LOGIN_URL = '/admin/' From 23c5cd11ad21f18eed11c9812c3a58925e1261bd Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:38:01 -0700 Subject: [PATCH 04/14] Adjust test matrix to only supported Python/Django pairs --- .github/workflows/test.yml | 23 ++++++++++++++++++++++- tox.ini | 19 ++++++++++--------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f44fa80..e2e1b2c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,10 +11,31 @@ jobs: max-parallel: 5 matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12-dev'] - django-version: ['3.2', '4.0', 'main'] + django-version: ['3.2', '4.0', '4.1', '4.2', 'main'] include: - python-version: '3.7' django-version: '3.2' + exclude: + - python-version: '3.11' + django-version: '3.2' + - python-version: '3.12-dev' + django-version: '3.2' + + - python-version: '3.11' + django-version: '4.0' + - python-version: '3.12-dev' + django-version: '4.0' + + - python-version: '3.12-dev' + django-version: '4.1' + + - python-version: '3.8' + django-version: 'main' + - python-version: '3.9' + django-version: 'main' + - python-version: '3.10' + django-version: 'main' + steps: - uses: actions/checkout@v3 diff --git a/tox.ini b/tox.ini index 1193d92..abae0dc 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,11 @@ ; Minimum version of Tox minversion = 1.8 envlist = + ; https://docs.djangoproject.com/en/4.2/faq/install/#what-python-version-can-i-use-with-django py{37}-dj32 - py{38,39,310,311,312}-dj{32,40,main} + py{38,39,310}-dj{32,40,41} + py{311}-dj41 + py{311,312}-dj{42,main} flake8 [gh-actions] @@ -17,11 +20,10 @@ python = [gh-actions:env] DJANGO = - 2.2: dj22 - 3.0: dj30 - 3.1: dj31 3.2: dj32 4.0: dj40 + 4.1: dj41 + 4.2: dj42 main: djmain [testenv] @@ -31,11 +33,10 @@ commands = coverage xml deps = coverage - dj22: Django<2.3 - dj30: Django<3.1 - dj31: Django<3.2 - dj32: Django<4.0 - dj40: Django<4.1 + dj32: Django>=3.2,<4.0 + dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 + dj42: Django>=4.2,<4.3 djmain: https://github.com/django/django/archive/main.tar.gz ignore_outcome = djmain: True From f950a3433e94c251130517e932e3c3518082c68a Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:39:54 -0700 Subject: [PATCH 05/14] Silence flake8 check --- user_sessions/templatetags/user_sessions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_sessions/templatetags/user_sessions.py b/user_sessions/templatetags/user_sessions.py index df68fa9..a5f78e0 100644 --- a/user_sessions/templatetags/user_sessions.py +++ b/user_sessions/templatetags/user_sessions.py @@ -98,7 +98,7 @@ def location(value): try: location = geoip() and geoip().country(value) except Exception as e: - warnings.warn(str(e)) + warnings.warn(str(e), stacklevel=2) location = None if location and location['country_name']: if 'city' in location and location['city']: @@ -118,5 +118,5 @@ def geoip(): try: _geoip = GeoIP2() except Exception as e: - warnings.warn(str(e)) + warnings.warn(str(e), stacklevel=2) return _geoip From b9951017f924d54f6abe6f69fc5088e0edd28e65 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:40:07 -0700 Subject: [PATCH 06/14] Use f-strings everywhere possible --- tests/tests.py | 6 +++--- user_sessions/admin.py | 2 +- user_sessions/templatetags/user_sessions.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index c60ffcd..8ec1909 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -139,19 +139,19 @@ def test_search(self): self.assertNotContains(response, '1.1.1.1') def test_mine(self): - my_sessions = '{}?{}'.format(self.admin_url, urlencode({'owner': 'my'})) + my_sessions = f"{self.admin_url}?{urlencode({'owner': 'my'})}" response = self.client.get(my_sessions) self.assertContains(response, '127.0.0.1') self.assertNotContains(response, '1.1.1.1') def test_expired(self): - expired = '{}?{}'.format(self.admin_url, urlencode({'active': '0'})) + expired = f"{self.admin_url}?{urlencode({'active': '0'})}" response = self.client.get(expired) self.assertContains(response, '20.13.1.1') self.assertNotContains(response, '1.1.1.1') def test_unexpired(self): - unexpired = '{}?{}'.format(self.admin_url, urlencode({'active': '1'})) + unexpired = f"{self.admin_url}?{urlencode({'active': '1'})}" response = self.client.get(unexpired) self.assertContains(response, '1.1.1.1') self.assertNotContains(response, '20.13.1.1') diff --git a/user_sessions/admin.py b/user_sessions/admin.py index eb11031..68e1145 100644 --- a/user_sessions/admin.py +++ b/user_sessions/admin.py @@ -49,7 +49,7 @@ class SessionAdmin(admin.ModelAdmin): def get_search_fields(self, request): User = get_user_model() - return ('ip', 'user__%s' % getattr(User, 'USERNAME_FIELD', 'username')) + return ('ip', f"user__{getattr(User, 'USERNAME_FIELD', 'username')}") def is_valid(self, obj): return obj.expire_date > now() diff --git a/user_sessions/templatetags/user_sessions.py b/user_sessions/templatetags/user_sessions.py index a5f78e0..7408213 100644 --- a/user_sessions/templatetags/user_sessions.py +++ b/user_sessions/templatetags/user_sessions.py @@ -102,7 +102,7 @@ def location(value): location = None if location and location['country_name']: if 'city' in location and location['city']: - return '{}, {}'.format(location['city'], location['country_name']) + return f"{location['city']}, {location['country_name']}" return location['country_name'] return None From 87d9d9caa174b4356562838d9c2f005133c73578 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:43:28 -0700 Subject: [PATCH 07/14] Generage and use fake mmdb files during tests --- .gitignore | 12 +++--- Makefile | 6 ++- tests/Dockerfile | 9 +++++ tests/generate_mmdb.pl | 89 ++++++++++++++++++++++++++++++++++++++++++ tests/settings.py | 7 +++- tox.ini | 4 +- 6 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 tests/Dockerfile create mode 100755 tests/generate_mmdb.pl diff --git a/.gitignore b/.gitignore index 7d3344a..800c70e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ /example/database.sqlite3 /example/GeoLiteCity.dat /django_user_sessions.egg-info/ +/tests/test_city.mmdb +/tests/test_country.mmdb /htmlcov/ @@ -10,8 +12,8 @@ coverage.xml /docs/_build/ /GeoLite2-City.mmdb - -__pycache__ -/venv/ -/.eggs/ -/build/ + +__pycache__ +/venv/ +/.eggs/ +/build/ diff --git a/Makefile b/Makefile index fa6870b..4a05d30 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,11 @@ check: DJANGO_SETTINGS_MODULE=example.settings PYTHONPATH=. \ python -Wd example/manage.py check -test: +generate-mmdb-fixtures: + docker --context=default buildx build -f tests/Dockerfile --tag test-mmdb-maker tests + docker run --rm --volume $$(pwd)/tests:/data test-mmdb-maker + +test: generate-mmdb-fixtures DJANGO_SETTINGS_MODULE=tests.settings PYTHONPATH=. \ django-admin.py test ${TARGET} diff --git a/tests/Dockerfile b/tests/Dockerfile new file mode 100644 index 0000000..d363dc6 --- /dev/null +++ b/tests/Dockerfile @@ -0,0 +1,9 @@ +FROM perl:latest + +RUN cpanm MaxMind::DB::Writer + +COPY generate_mmdb.pl / + +VOLUME ["/data"] + +CMD ["perl", "/generate_mmdb.pl"] diff --git a/tests/generate_mmdb.pl b/tests/generate_mmdb.pl new file mode 100755 index 0000000..2b2f5b6 --- /dev/null +++ b/tests/generate_mmdb.pl @@ -0,0 +1,89 @@ +#!perl + +use MaxMind::DB::Writer::Tree; + +my %city_types = ( + city => 'map', + code => 'utf8_string', + continent => 'map', + country => 'map', + en => 'utf8_string', + is_in_european_union => 'boolean', + iso_code => 'utf8_string', + latitude => 'double', + location => 'map', + longitude => 'double', + metro_code => 'utf8_string', + names => 'map', + postal => 'map', + subdivisions => ['array', 'map'], + region => 'utf8_string', + time_zone => 'utf8_string', +); + +my $city_tree = MaxMind::DB::Writer::Tree->new( + ip_version => 6, + record_size => 24, + database_type => 'GeoLite2-City', + languages => ['en'], + description => { en => 'Test database of IP city data' }, + map_key_type_callback => sub { $city_types{ $_[0] } }, +); + +$city_tree->insert_network( + '44.55.66.77/32', + { + city => { names => {en => 'San Diego'} }, + continent => { code => 'NA', names => {en => 'North America'} }, + country => { iso_code => 'US', names => {en => 'United States'} }, + is_in_european_union => false, + location => { + latitude => 37.751, + longitude => -97.822, + metro_code => 'custom metro code', + time_zone => 'America/Los Angeles', + }, + postal => { code => 'custom postal code' }, + subdivisions => [ + { iso_code => 'ABC', names => {en => 'Absolute Basic Class'} }, + ], + }, +); + +my $outfile = ($ENV{'DATA_DIR'} || '/data/') . ($ENV{'CITY_FILENAME'} || 'test_city.mmdb'); +open my $fh, '>:raw', $outfile; +$city_tree->write_tree($fh); + + + +my %country_types = ( + country => 'map', + iso_code => 'utf8_string', + names => 'map', + en => 'utf8_string', +); + +my $country_tree = MaxMind::DB::Writer::Tree->new( + ip_version => 6, + record_size => 24, + database_type => 'GeoLite2-Country', + languages => ['en'], + description => { en => 'Test database of IP country data' }, + map_key_type_callback => sub { $country_types{ $_[0] } }, +); + +$country_tree->insert_network( + '8.8.8.8/32', + { + country => { + iso_code => 'US', + names => { + en => 'United States', + }, + }, + }, +); + +my $outfile = ($ENV{'DATA_DIR'} || '/data/') . ($ENV{'COUNTRY_FILENAME'} || 'test_country.mmdb'); +open my $fh, '>:raw', $outfile; +$country_tree->write_tree($fh); diff --git a/tests/settings.py b/tests/settings.py index 5ea39af..ed1c9d4 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,7 +1,7 @@ from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent +BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' @@ -56,7 +56,10 @@ }, ] -GEOIP_PATH = BASE_DIR.parent / 'GeoLite2-City.mmdb' +GEOIP_PATH = BASE_DIR / 'tests' +GEOIP_CITY = 'test_city.mmdb' +GEOIP_COUNTRY = 'test_country.mmdb' + SESSION_ENGINE = 'user_sessions.backends.db' LOGIN_URL = '/admin/' diff --git a/tox.ini b/tox.ini index abae0dc..d1a8b60 100644 --- a/tox.ini +++ b/tox.ini @@ -28,6 +28,7 @@ DJANGO = [testenv] commands = + make generate-mmdb-fixtures coverage run {envbindir}/django-admin test -v 2 --pythonpath=./ --settings=tests.settings coverage report coverage xml @@ -38,9 +39,10 @@ deps = dj41: Django>=4.1,<4.2 dj42: Django>=4.2,<4.3 djmain: https://github.com/django/django/archive/main.tar.gz + geoip2 ignore_outcome = djmain: True -whitelist_externals = make +allowlist_externals = make [testenv:flake8] basepython = python3.11 From d4e8ec5e1ea449d77f0e70558a4d37ed3f71e6ce Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:44:42 -0700 Subject: [PATCH 08/14] Test for/silence user warnings that IP wasn't found in database --- tests/tests.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 8ec1909..042ee13 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -82,7 +82,8 @@ def test_list(self): self.user.session_set.create(session_key='ABC123', ip='127.0.0.1', expire_date=datetime.now() + timedelta(days=1), user_agent='Firefox') - response = self.client.get(reverse('user_sessions:session_list')) + with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): + response = self.client.get(reverse('user_sessions:session_list')) self.assertContains(response, 'Active Sessions') self.assertContains(response, 'Firefox') self.assertNotContains(response, 'ABC123') @@ -97,7 +98,8 @@ def test_delete_all_other(self): self.user.session_set.create(ip='127.0.0.1', expire_date=datetime.now() + timedelta(days=1)) self.assertEqual(self.user.session_set.count(), 2) response = self.client.post(reverse('user_sessions:session_delete_other')) - self.assertRedirects(response, reverse('user_sessions:session_list')) + with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): + self.assertRedirects(response, reverse('user_sessions:session_list')) self.assertEqual(self.user.session_set.count(), 1) def test_delete_some_other(self): @@ -106,7 +108,8 @@ def test_delete_some_other(self): self.assertEqual(self.user.session_set.count(), 2) response = self.client.post(reverse('user_sessions:session_delete', args=[other.session_key])) - self.assertRedirects(response, reverse('user_sessions:session_list')) + with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): + self.assertRedirects(response, reverse('user_sessions:session_list')) self.assertEqual(self.user.session_set.count(), 1) @@ -126,33 +129,38 @@ def setUp(self): self.admin_url = reverse('admin:user_sessions_session_changelist') def test_list(self): - response = self.client.get(self.admin_url) + with self.assertWarnsRegex(UserWarning, r"The address 1\.1\.1\.1 is not in the database"): + response = self.client.get(self.admin_url) self.assertContains(response, 'Select session to change') self.assertContains(response, '127.0.0.1') self.assertContains(response, '20.13.1.1') self.assertContains(response, '1.1.1.1') def test_search(self): - response = self.client.get(self.admin_url, {'q': 'bouke'}) + with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): + response = self.client.get(self.admin_url, {'q': 'bouke'}) self.assertContains(response, '127.0.0.1') self.assertNotContains(response, '20.13.1.1') self.assertNotContains(response, '1.1.1.1') def test_mine(self): my_sessions = f"{self.admin_url}?{urlencode({'owner': 'my'})}" - response = self.client.get(my_sessions) + with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): + response = self.client.get(my_sessions) self.assertContains(response, '127.0.0.1') self.assertNotContains(response, '1.1.1.1') def test_expired(self): expired = f"{self.admin_url}?{urlencode({'active': '0'})}" - response = self.client.get(expired) + with self.assertWarnsRegex(UserWarning, r"The address 20\.13\.1\.1 is not in the database"): + response = self.client.get(expired) self.assertContains(response, '20.13.1.1') self.assertNotContains(response, '1.1.1.1') def test_unexpired(self): unexpired = f"{self.admin_url}?{urlencode({'active': '1'})}" - response = self.client.get(unexpired) + with self.assertWarnsRegex(UserWarning, r"The address 1\.1\.1\.1 is not in the database"): + response = self.client.get(unexpired) self.assertContains(response, '1.1.1.1') self.assertNotContains(response, '20.13.1.1') @@ -314,7 +322,12 @@ def test_no_session(self): class LocationTemplateFilterTest(TestCase): @override_settings(GEOIP_PATH=None) def test_no_location(self): - self.assertEqual(location('127.0.0.1'), None) + with self.assertWarnsRegex( + UserWarning, + r"The address 127\.0\.0\.1 is not in the database", + ): + loc = location('127.0.0.1') + self.assertEqual(loc, None) @skipUnless(geoip, geoip_msg) def test_locations(self): From c94a2e1be8fac1bf9796ba16da4144fe8bf1d468 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 01:45:43 -0700 Subject: [PATCH 09/14] Add city and country templatetags --- tests/tests.py | 12 +++++++++++- user_sessions/templatetags/user_sessions.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index 042ee13..2cce029 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -15,7 +15,9 @@ from user_sessions.backends.db import SessionStore from user_sessions.models import Session -from user_sessions.templatetags.user_sessions import device, location +from user_sessions.templatetags.user_sessions import ( + city, country, device, location, +) from user_sessions.utils.tests import Client try: @@ -329,6 +331,14 @@ def test_no_location(self): loc = location('127.0.0.1') self.assertEqual(loc, None) + @skipUnless(geoip, geoip_msg) + def test_city(self): + self.assertEqual('San Diego', city('44.55.66.77')) + + @skipUnless(geoip, geoip_msg) + def test_country(self): + self.assertEqual('United States', country('8.8.8.8')) + @skipUnless(geoip, geoip_msg) def test_locations(self): self.assertEqual('United States', location('8.8.8.8')) diff --git a/user_sessions/templatetags/user_sessions.py b/user_sessions/templatetags/user_sessions.py index 7408213..30d45c6 100644 --- a/user_sessions/templatetags/user_sessions.py +++ b/user_sessions/templatetags/user_sessions.py @@ -81,6 +81,22 @@ def device(value): return None +@register.filter +def city(value): + location = geoip() and geoip().city(value) + if location and location['city']: + return location['city'] + return None + + +@register.filter +def country(value): + location = geoip() and geoip().country(value) + if location and location['country_name']: + return location['country_name'] + return None + + @register.filter def location(value): """ From c20a3a634bb152dd31a1dade15c8f30c83271fd0 Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 02:52:31 -0700 Subject: [PATCH 10/14] Use timezone-aware now() --- tests/tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 2cce029..2d7fec1 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,4 +1,4 @@ -from datetime import datetime, timedelta +from datetime import timedelta from unittest import skipUnless from unittest.mock import patch from urllib.parse import urlencode @@ -82,7 +82,7 @@ def setUp(self): def test_list(self): self.user.session_set.create(session_key='ABC123', ip='127.0.0.1', - expire_date=datetime.now() + timedelta(days=1), + expire_date=now() + timedelta(days=1), user_agent='Firefox') with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): response = self.client.get(reverse('user_sessions:session_list')) @@ -97,7 +97,7 @@ def test_delete(self): self.assertRedirects(response, '/') def test_delete_all_other(self): - self.user.session_set.create(ip='127.0.0.1', expire_date=datetime.now() + timedelta(days=1)) + self.user.session_set.create(ip='127.0.0.1', expire_date=now() + timedelta(days=1)) self.assertEqual(self.user.session_set.count(), 2) response = self.client.post(reverse('user_sessions:session_delete_other')) with self.assertWarnsRegex(UserWarning, r"The address 127\.0\.0\.1 is not in the database"): @@ -106,7 +106,7 @@ def test_delete_all_other(self): def test_delete_some_other(self): other = self.user.session_set.create(session_key='OTHER', ip='127.0.0.1', - expire_date=datetime.now() + timedelta(days=1)) + expire_date=now() + timedelta(days=1)) self.assertEqual(self.user.session_set.count(), 2) response = self.client.post(reverse('user_sessions:session_delete', args=[other.session_key])) @@ -502,7 +502,7 @@ def test_windows_only(self): class ClearsessionsCommandTest(TestCase): def test_can_call(self): - Session.objects.create(expire_date=datetime.now() - timedelta(days=1), + Session.objects.create(expire_date=now() - timedelta(days=1), ip='127.0.0.1') call_command('clearsessions') self.assertEqual(Session.objects.count(), 0) From 4598d888335c93ba5c5e211052df9ec407dd757f Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 02:53:09 -0700 Subject: [PATCH 11/14] Allow jobs run with -dev Python versions or with Django main to fail without failing the entire test run --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e2e1b2c..a7377a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,6 +52,7 @@ jobs: python -m pip install --upgrade tox tox-gh-actions - name: Tox tests + continue-on-error: ${{ endsWith(matrix.python-version, '-dev') || matrix.django-version == 'main' }} run: | tox -v env: From 12cc8b6dfeb0383fd33e1444d3ff0dcfdaadb34d Mon Sep 17 00:00:00 2001 From: blag Date: Tue, 19 Sep 2023 18:06:21 -0700 Subject: [PATCH 12/14] Ignore geoip fallback in tests/tests.py --- tests/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index 2d7fec1..f849828 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -24,7 +24,7 @@ from django.contrib.gis.geoip2 import GeoIP2 geoip = GeoIP2() geoip_msg = None -except Exception as error_geoip2: +except Exception as error_geoip2: # pragma: no cover try: from django.contrib.gis.geoip import GeoIP geoip = GeoIP() From b7d16690c372f5ecb5189e731806216b68299f23 Mon Sep 17 00:00:00 2001 From: blag Date: Thu, 21 Sep 2023 15:57:47 -0700 Subject: [PATCH 13/14] Move test utils out of distributed package --- docs/reference.rst | 4 ---- tests/tests.py | 3 ++- user_sessions/utils/tests.py => tests/utils.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) rename user_sessions/utils/tests.py => tests/utils.py (98%) diff --git a/docs/reference.rst b/docs/reference.rst index 420a3d2..82eae50 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -22,7 +22,3 @@ Views ----- .. autoclass:: user_sessions.views.SessionListView .. autoclass:: user_sessions.views.SessionDeleteView - -Unit tests ----------- -.. autoclass:: user_sessions.utils.tests.Client diff --git a/tests/tests.py b/tests/tests.py index f849828..dbc3f6d 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -18,7 +18,8 @@ from user_sessions.templatetags.user_sessions import ( city, country, device, location, ) -from user_sessions.utils.tests import Client + +from .utils import Client try: from django.contrib.gis.geoip2 import GeoIP2 diff --git a/user_sessions/utils/tests.py b/tests/utils.py similarity index 98% rename from user_sessions/utils/tests.py rename to tests/utils.py index bc1eb32..fb3463e 100644 --- a/user_sessions/utils/tests.py +++ b/tests/utils.py @@ -3,7 +3,7 @@ from django.http import HttpRequest from django.test import Client as BaseClient -from ..backends.db import SessionStore +from user_sessions.backends.db import SessionStore class Client(BaseClient): From c1a931bbc1ca4c9ed7203906f61a277867503dc9 Mon Sep 17 00:00:00 2001 From: blag Date: Wed, 4 Oct 2023 20:39:16 -0700 Subject: [PATCH 14/14] Fix warning during tests --- tests/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/settings.py b/tests/settings.py index ed1c9d4..1ff458a 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -48,6 +48,7 @@ 'django.template.context_processors.debug', 'django.template.context_processors.i18n', 'django.template.context_processors.media', + 'django.template.context_processors.request', 'django.template.context_processors.static', 'django.template.context_processors.tz', 'django.contrib.messages.context_processors.messages', @@ -65,4 +66,4 @@ LOGIN_URL = '/admin/' LOGOUT_REDIRECT_URL = '/' -SILENCED_SYSTEM_CHECKS = ['admin.E406', 'admin.E409', 'admin.E410', 'admin.W411'] +SILENCED_SYSTEM_CHECKS = ['admin.E406', 'admin.E409', 'admin.E410']