Skip to content

Commit

Permalink
Merge pull request zsoldosp#62 from asucrews/master
Browse files Browse the repository at this point in the history
Adding support for django 4
  • Loading branch information
belugame authored May 11, 2022
2 parents b32c42a + 1ea8ca3 commit e047eec
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 67 deletions.
14 changes: 6 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ install:
- pip install tox
matrix:
include:
- python: "2.7"
env: TOX_ENVS=py27-django111
- python: "3.5"
env: TOX_ENVS=py35-django21,py35-django22
- python: "3.6"
env: TOX_ENVS=py36-django21,py36-django22,py36-django30,py36-django31,py36-django32
env: TOX_ENVS=py36-django30,py36-django31,py36-django32
- python: "3.7"
env: TOX_ENVS=py37-django21,py37-django22,py37-django30,py37-django31,py37-django32
env: TOX_ENVS=py37-django30,py37-django31,py37-django32
- python: "3.8"
env: TOX_ENVS=py38-django21,py38-django22,py38-django30,py38-django31,py38-django32
env: TOX_ENVS=py38-django30,py38-django31,py38-django32,py310-django40
- python: "3.9"
env: TOX_ENVS=py39-django22,py39-django30,py39-django31,py39-django32
env: TOX_ENVS=py39-django30,py39-django31,py39-django32,py310-django40
- python: "3.10"
env: TOX_ENVS=py39-django30,py39-django31,py39-django32,py310-django40
script:
- tox -e $TOX_ENVS
before_deploy: "make clean"
Expand Down
2 changes: 1 addition & 1 deletion django_currentuser/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.5.3'
__version__ = '0.5.4'
8 changes: 8 additions & 0 deletions django_currentuser/db/models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class CurrentUserField(models.ForeignKey):

def __init__(self, *args, **kwargs):
self.on_update = kwargs.pop("on_update", False)

# If `to` is present in kwargs, and the same when ignoring case then
# update `to` to use the defaults.
# Fix for https://github.com/PaesslerAG/django-currentuser/issues/43
if "to" in kwargs \
and kwargs["to"].lower() == self.defaults['to'].lower():
kwargs["to"] = self.defaults['to']

self._warn_for_shadowing_args(*args, **kwargs)

if "on_delete" not in kwargs:
Expand Down
15 changes: 13 additions & 2 deletions django_currentuser/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ def _set_current_user(user=None):
_do_set_current_user(lambda self: user)


class SetCurrentUser:
def __init__(this, request):
this.request = request

def __enter__(this):
_do_set_current_user(lambda self: getattr(this.request, 'user', None))

def __exit__(this, type, value, traceback):
_do_set_current_user(lambda self: None)


class ThreadLocalUserMiddleware(object):

def __init__(self, get_response):
Expand All @@ -30,8 +41,8 @@ def __call__(self, request):
# request.user closure; asserts laziness;
# memorization is implemented in
# request.user (non-data descriptor)
_do_set_current_user(lambda self: getattr(request, 'user', None))
response = self.get_response(request)
with SetCurrentUser(request):
response = self.get_response(request)
return response


Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[wheel]
universal = 1
universal = 1
15 changes: 4 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
],
include_package_data=True,
install_requires=[
'Django>=1.11.17,<3.3;python_version>="2.7"',
'Django>=1.11.17,<5.0;python_version>="2.7"',
],
license="BSD",
zip_safe=False,
Expand All @@ -41,20 +41,13 @@
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Framework :: Django :: 3',
'Framework :: Django :: 4',
],
)
86 changes: 53 additions & 33 deletions tests/testapp/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from hamcrest import assert_that, instance_of, equal_to, is_, empty, has_length

from django_currentuser.middleware import (
get_current_user, _set_current_user, get_current_authenticated_user)
SetCurrentUser,
get_current_user,
_set_current_user,
get_current_authenticated_user
)
from django_currentuser.db.models import CurrentUserField

from .sixmock import patch
Expand All @@ -30,23 +34,29 @@ def setUp(self):
self.user2.set_password("pw2")
self.user2.save()

def login_and_go_to_homepage(self, username, password):
def login_and_create(self, username, password):
data = {"username": username, "password": password}
self.client.post(reverse("login"), follow=True, data=data)
self.client.get('/')
self.client.post(reverse("create"), follow=True, data=data)

def login_and_update(self, username, password, pk):
data = {"username": username, "password": password}
self.client.post(reverse("login"), follow=True, data=data)
self.client.patch(reverse("update", args=[pk]), follow=True, data=data)


class TestSetUserToThread(TestUserBase):

@patch.object(SetCurrentUser, "__exit__", lambda *args, **kwargs: None)
def test__local_thread_var_is_set_to_logged_in_user(self):
_set_current_user(None)
self.assertIsNone(get_current_user())

self.login_and_go_to_homepage(username="user1", password="pw1")
self.login_and_create(username="user1", password="pw1")
self.assertEqual(self.user1, get_current_user())
self.client.logout()

self.login_and_go_to_homepage(username="user2", password="pw2")
self.login_and_create(username="user2", password="pw2")
self.assertEqual(self.user2, get_current_user())
self.client.logout()

Expand Down Expand Up @@ -106,6 +116,16 @@ def test_raises_warning_when_non_default_arguments_are_passed(self):
assert_that([str(m.message) for m in my_warnings],
is_([CurrentUserField.warning] * 4))

def test_no_warning_raised_when_upper_case_user_model_passed(self):
with warnings.catch_warnings(record=True) as my_warnings:
self.field_cls(to='auth.User')
assert_that(my_warnings, has_length(0))

def test_no_warning_raised_when_lower_case_user_model_passed(self):
with warnings.catch_warnings(record=True) as my_warnings:
self.field_cls(to='auth.user')
assert_that(my_warnings, has_length(0))

def test_no_warning_raised_if_passed_argument_values_match_defaults(self):
with warnings.catch_warnings(record=True) as my_warnings:
self.field_cls(default=get_current_authenticated_user)
Expand Down Expand Up @@ -140,49 +160,49 @@ def test_on_update_enabled(self):
test_model.save()

self.assertIs(test_model.updated_by_id, None)
test_model.refresh_from_db()
self.assertIs(test_model.updated_by, None)

self.login_and_go_to_homepage(username="user1", password="pw1")
test_model.save()
self.login_and_update(username="user1", password="pw1", pk=1)
user = TestModelOnUpdate.objects.get(pk=1)

self.assertEqual(self.user1.pk, test_model.updated_by_id)
test_model.refresh_from_db()
self.assertEqual(self.user1, test_model.updated_by)
self.assertEqual(self.user1.pk, user.updated_by_id)
self.assertEqual(self.user1, user.updated_by)

self.login_and_go_to_homepage(username="user2", password="pw2")
test_model.save()
self.login_and_update(username="user2", password="pw2", pk=1)
user = TestModelOnUpdate.objects.get(pk=1)

self.assertEqual(self.user2.pk, test_model.updated_by_id)
test_model.refresh_from_db()
self.assertEqual(self.user2, test_model.updated_by)
self.assertEqual(self.user2.pk, user.updated_by_id)
self.assertEqual(self.user2, user.updated_by)

_set_current_user(None)
test_model.save()
user = TestModelOnUpdate.objects.get(pk=1)

self.assertIs(test_model.updated_by_id, None)
test_model.refresh_from_db()
self.assertIs(test_model.updated_by, None)

def test_on_update_disabled(self):
self.login_and_go_to_homepage(username="user1", password="pw1")
test_model = TestModelDefaultBehavior()
test_model.save()
self.login_and_create(username="user1", password="pw1")
user1 = TestModelDefaultBehavior.objects.get(pk=1)

self.assertEqual(self.user1.pk, test_model.created_by_id)
test_model.refresh_from_db()
self.assertEqual(self.user1, test_model.created_by)
self.assertEqual(self.user1.pk, user1.created_by_id)
self.assertEqual(self.user1, user1.created_by)

self.login_and_go_to_homepage(username="user2", password="pw2")
test_model.save()
self.login_and_create(username="user2", password="pw2")
user1 = TestModelDefaultBehavior.objects.get(pk=1)
user2 = TestModelDefaultBehavior.objects.get(pk=2)

self.assertEqual(self.user1.pk, test_model.created_by_id)
test_model.refresh_from_db()
self.assertEqual(self.user1, test_model.created_by)
self.assertEqual(self.user1.pk, user1.created_by_id)
self.assertEqual(self.user1, user1.created_by)
self.assertEqual(self.user2.pk, user2.created_by_id)
self.assertEqual(self.user2, user2.created_by)

_set_current_user(None)
test_model.save()

self.assertEqual(self.user1.pk, test_model.created_by_id)
test_model.refresh_from_db()
self.assertEqual(self.user1, test_model.created_by)
TestModelDefaultBehavior().save()
user1 = TestModelDefaultBehavior.objects.get(pk=1)
user2 = TestModelDefaultBehavior.objects.get(pk=2)

self.assertEqual(self.user1.pk, user1.created_by_id)
self.assertEqual(self.user1, user1.created_by)
self.assertEqual(self.user2.pk, user2.created_by_id)
self.assertEqual(self.user2, user2.created_by)
19 changes: 18 additions & 1 deletion tests/testapp/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import django
from django.contrib.auth import views as auth_views
from django.http import HttpResponse

from .models import TestModelDefaultBehavior, TestModelOnUpdate


if django.VERSION < (2, 0):
Expand All @@ -8,6 +11,20 @@
from django.urls import path


def create(request):
if request.method == 'POST':
TestModelDefaultBehavior.objects.create()
return HttpResponse()


def update(request, pk):
if request.method == 'PATCH':
TestModelOnUpdate.objects.get(pk=pk).save()
return HttpResponse()


urlpatterns = [
path(r'login/', auth_views.LoginView.as_view(), name="login")
path(r'login/', auth_views.LoginView.as_view(), name="login"),
path(r'create/', create, name="create"),
path(r'update/<int:pk>/', update, name="update")
]
13 changes: 3 additions & 10 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
[tox]
envlist =
py{27,36,37}-django111,
py{36,37,38}-django21,
py{36,37,38,39}-django22,
py{36,37,38,39}-django30,
py{36,37,38,39}-django31,
py{36,37,38,39}-django32,
py{36,37,38,39,310}-django32,
py{38,39,310}-django40,

[testenv]
commands =
Expand All @@ -16,15 +14,10 @@ setenv =
DJANGO_SETTINGS_MODULE = settings
PIP_INDEX_URL = https://pypi.python.org/simple/
deps =
py27: mock
py27: pyhamcrest==1.9.0
!py27: pyhamcrest
django111: Django>=1.11.17,<1.12
django21: Django>=2.1.8,<2.2
django22: Django>=2.2.1,<2.3
django30: Django>=3.0,<3.1
django31: Django>=3.1,<3.2
django32: Django>=3.2,<3.3
django40: Django>=4.0,<5.0
flake8
docutils

Expand Down

0 comments on commit e047eec

Please sign in to comment.