From b0ca0b47041dc61d9f41a5ba5a68c842b6db8078 Mon Sep 17 00:00:00 2001 From: Ilkay Celik Gulsoy Date: Thu, 11 Jan 2024 19:08:38 -0800 Subject: [PATCH 1/4] removed mock, six --- Makefile | 2 +- baya/backend.py | 3 +-- baya/mock_ldap_helpers.py | 2 +- baya/permissions.py | 9 ++++----- baya/tests/test_admin.py | 9 ++++----- baya/tests/test_backend.py | 4 ++-- baya/tests/test_dynamic_roles.py | 4 ++-- baya/tests/test_nodes.py | 2 +- baya/tests/test_permissions.py | 9 ++++----- baya/tests/test_visitors.py | 2 +- baya/utils.py | 3 +-- requirements-dev.txt | 1 - setup.py | 2 -- 13 files changed, 22 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index c653827..6a27989 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ default: venv: $(VENV_ACTIVATE) $(VENV_ACTIVATE): requirements*.txt setup.py - test -f $@ || virtualenv --python=$(PYTHON) $(VENV_DIR) + test -f $@ || python3 -m venv $(VENV_DIR) || virtualenv --python=$(PYTHON) $(VENV_DIR) $(WITH_VENV) pip install --no-deps -r requirements-setup.txt $(WITH_VENV) pip install -e . $(WITH_VENV) pip install --no-deps -r requirements-dev.txt diff --git a/baya/backend.py b/baya/backend.py index bc6c30d..278a310 100644 --- a/baya/backend.py +++ b/baya/backend.py @@ -1,5 +1,4 @@ from functools import partial -import six from django.conf import settings from django.contrib.auth import get_permission_codename @@ -34,7 +33,7 @@ def get_all_permissions(self, user, obj=None): user, obj) from baya.admin.sites import _admin_registry for admin_site in _admin_registry: - for model, opts in six.iteritems(admin_site._registry): + for model, opts in admin_site._registry.items(): app = model._meta.app_label perm_name = partial(get_permission_codename, opts=model._meta) if (hasattr(opts, 'user_has_add_permission') and diff --git a/baya/mock_ldap_helpers.py b/baya/mock_ldap_helpers.py index ffeaf4a..d2af892 100644 --- a/baya/mock_ldap_helpers.py +++ b/baya/mock_ldap_helpers.py @@ -149,8 +149,8 @@ def mock_ldap_setup( `.start()` on the returned value. """ from django.conf import settings - import mock import mockldap + from unittest import mock class MockLDAP(mockldap.MockLdap): def start(self, *args, **kwargs): diff --git a/baya/permissions.py b/baya/permissions.py index 38501f5..df47372 100644 --- a/baya/permissions.py +++ b/baya/permissions.py @@ -16,7 +16,6 @@ elif django.VERSION[0] >= 2: from django.urls.resolvers import URLPattern from django.urls.resolvers import URLResolver -import six from .membership import BaseNode from .membership import ValueNode @@ -87,7 +86,7 @@ def _ensure_permission_node(self, groups): if groups is None: groups = [] - elif isinstance(groups, six.string_types): + elif isinstance(groups, str): groups = [group.strip() for group in groups.split(',')] return self.DEFAULT_PERMISSION_NODE(*groups) @@ -184,10 +183,10 @@ def __iadd__(self, other): self.get_requires &= other.get_requires self.post_requires &= other.post_requires # Prefer other's login_url, if set - login_text_type = six.text_type(settings.BAYA_LOGIN_URL) + login_text_type = str(settings.BAYA_LOGIN_URL) if ( other.login_url is not None and - six.text_type(other.login_url) != login_text_type + str(other.login_url) != login_text_type ): self.login_url = other.login_url return self @@ -374,7 +373,7 @@ def __call__(self, fn, *args, **kwargs): raise TypeError("Cannot decorate Inlines. See " "baya.admin.options.BayaInline instead.") return self.decorate_admin(fn, *args, **kwargs) - elif isinstance(fn, six.string_types): + elif isinstance(fn, str): raise TypeError("Cannot decorate string-path to view: %s." % fn) else: # You'll probably only get here if you're trying to decorate diff --git a/baya/tests/test_admin.py b/baya/tests/test_admin.py index c12cbc9..2865da2 100644 --- a/baya/tests/test_admin.py +++ b/baya/tests/test_admin.py @@ -1,4 +1,3 @@ -import six from django.contrib.admin.options import InlineModelAdmin from baya import RolesNode as g @@ -12,8 +11,8 @@ from baya.tests.models import BlagEntry from baya.tests.submod.models import Comment from baya.tests.test_base import LDAPGroupAuthTestBase -import mock -from mock import MagicMock +from unittest import mock +from unittest.mock import MagicMock class TestAdminSite(LDAPGroupAuthTestBase): @@ -62,7 +61,7 @@ def test_index(self): app_list = index.context_data['app_list'] self.assertEqual(len(app_list), 2) for app in app_list: - models = {six.text_type(model['name']) for model in app['models']} + models = {str(model['name']) for model in app['models']} if len(models) == 2: self.assertEqual({"Blags", "Entries"}, models) for model in app['models']: @@ -84,7 +83,7 @@ def test_read_only(self): app_list = app_list[0] self.assertEqual( {"Blags"}, - {six.text_type(model['name']) for model in app_list['models']}) + {str(model['name']) for model in app_list['models']}) perms = app_list['models'][0]['perms'] self.assertFalse(perms['add']) self.assertTrue(perms['change']) diff --git a/baya/tests/test_backend.py b/baya/tests/test_backend.py index f621081..a21052d 100644 --- a/baya/tests/test_backend.py +++ b/baya/tests/test_backend.py @@ -1,7 +1,7 @@ import ldap from django.test import TestCase -from mock import Mock -from mock import sentinel +from unittest.mock import Mock +from unittest.mock import sentinel from baya.backend import NestedLDAPGroupsBackend from baya.backend import ReconnectingLDAP diff --git a/baya/tests/test_dynamic_roles.py b/baya/tests/test_dynamic_roles.py index 88f7525..a4f9e9e 100644 --- a/baya/tests/test_dynamic_roles.py +++ b/baya/tests/test_dynamic_roles.py @@ -1,5 +1,5 @@ -from mock import MagicMock -from mock import patch +from unittest.mock import MagicMock +from unittest.mock import patch from unittest import TestCase diff --git a/baya/tests/test_nodes.py b/baya/tests/test_nodes.py index 0e09900..f24f7d8 100644 --- a/baya/tests/test_nodes.py +++ b/baya/tests/test_nodes.py @@ -1,4 +1,4 @@ -from mock import Mock +from unittest.mock import Mock from operator import and_ from operator import or_ diff --git a/baya/tests/test_permissions.py b/baya/tests/test_permissions.py index d66cc98..2d13f8c 100644 --- a/baya/tests/test_permissions.py +++ b/baya/tests/test_permissions.py @@ -1,9 +1,8 @@ import functools -from mock import patch -from mock import sentinel +from unittest.mock import patch +from unittest.mock import sentinel from types import FunctionType -import six import django from django.conf import settings if django.VERSION[:2] < (4, 0): @@ -159,8 +158,8 @@ def test_redirect(self): custom_login = "/testlogin/" g3 = Gate(login_url=custom_login) self.assertEqual(g3.login_url, custom_login) - self.assertEqual(six.text_type((g3 + g2).login_url), - six.text_type(custom_login)) + self.assertEqual(str((g3 + g2).login_url), + str(custom_login)) self.assertEqual((g2 + g3).login_url, custom_login) with override_settings(BAYA_LOGIN_URL="/testlogin/"): g4 = Gate() diff --git a/baya/tests/test_visitors.py b/baya/tests/test_visitors.py index 9a5be02..862562f 100644 --- a/baya/tests/test_visitors.py +++ b/baya/tests/test_visitors.py @@ -1,4 +1,4 @@ -from mock import MagicMock +from unittest.mock import MagicMock from unittest import TestCase from ..dynamic_roles import DjangoRequestGroupFormatter diff --git a/baya/utils.py b/baya/utils.py index 2e48398..a10a361 100644 --- a/baya/utils.py +++ b/baya/utils.py @@ -1,4 +1,3 @@ -import six from ldap.dn import str2dn from .membership import RolesNode as g @@ -22,7 +21,7 @@ def user_in_group(user, group, **kwargs): user_groups = set() if hasattr(user, 'ldap_user'): user_groups = group_names(user.ldap_user.group_dns) - if isinstance(group, six.string_types): + if isinstance(group, str): group = g(group) return PermissionChecker(user_groups).visit(group, **kwargs) diff --git a/requirements-dev.txt b/requirements-dev.txt index 63dad64..f1a51c6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,6 @@ coverage==5.1 django-nose==1.4.6 funcparserlib==0.3.6 -mock==1.0.1 mockldap==0.2.6 nose==1.3.7 pycodestyle==2.9.1 diff --git a/setup.py b/setup.py index 8d93da9..e4e4384 100644 --- a/setup.py +++ b/setup.py @@ -40,8 +40,6 @@ def load_version(): "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", From a8c8945da6472300e8135c6be51a7faa42bb214e Mon Sep 17 00:00:00 2001 From: Ilkay Celik Gulsoy Date: Thu, 11 Jan 2024 19:31:57 -0800 Subject: [PATCH 2/4] tests run --- Makefile | 1 + baya/tests/test_base.py | 2 +- requirements-setup.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6a27989..d9f015a 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ default: venv: $(VENV_ACTIVATE) $(VENV_ACTIVATE): requirements*.txt setup.py + pip install virtualenv==20.8.1 test -f $@ || python3 -m venv $(VENV_DIR) || virtualenv --python=$(PYTHON) $(VENV_DIR) $(WITH_VENV) pip install --no-deps -r requirements-setup.txt $(WITH_VENV) pip install -e . diff --git a/baya/tests/test_base.py b/baya/tests/test_base.py index 04763bd..210efe7 100644 --- a/baya/tests/test_base.py +++ b/baya/tests/test_base.py @@ -1,4 +1,4 @@ -from mock import MagicMock +from unittest.mock import MagicMock import django from django_auth_ldap import backend diff --git a/requirements-setup.txt b/requirements-setup.txt index b0c2dda..eb1815f 100644 --- a/requirements-setup.txt +++ b/requirements-setup.txt @@ -1,6 +1,6 @@ # Requirements needed for the setup make target and the test target # outside of the individual tox environments. - +setuptools<58.0 pluggy==1.0.0 py==1.11.0 tox==3.27.1 From 4dd2c99194b6294f3ce207cc8d319a2548a1316d Mon Sep 17 00:00:00 2001 From: Ilkay Celik Gulsoy Date: Fri, 12 Jan 2024 11:12:39 -0800 Subject: [PATCH 3/4] update collections logic --- baya/permissions.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/baya/permissions.py b/baya/permissions.py index df47372..1168e36 100644 --- a/baya/permissions.py +++ b/baya/permissions.py @@ -1,9 +1,10 @@ -import collections import functools -import sys -if sys.version_info[:2] >= (3, 10): - collections.Callable = collections.abc.Callable +try: + from collections.abc import Callable +except: + from collections import Callable + import django from django.conf import settings @@ -361,7 +362,7 @@ def __call__(self, fn, *args, **kwargs): 'Cannot decorate a bare functools.partial view. ' 'You must invoke functools.update_wrapper(partial_view, ' 'full_view) first.') - if not isinstance(fn, type) and isinstance(fn, collections.Callable): + if not isinstance(fn, type) and isinstance(fn, Callable): return self.decorate_method(fn, *args, **kwargs) elif isinstance(fn, tuple): # Must be an include('my_app.urls') we're decorating From b8444f80abc0730bcae85319ebd1aabd260b14fe Mon Sep 17 00:00:00 2001 From: Ilkay Celik Gulsoy Date: Mon, 1 Apr 2024 17:06:36 -0700 Subject: [PATCH 4/4] more modernization --- CHANGELOG | 2 +- Makefile | 24 +++- baya/permissions.py | 2 +- baya/tests/settings.py | 5 +- baya/tests/test_admin.py | 115 ++++++++++--------- baya/tests/test_backend.py | 10 +- baya/tests/test_base.py | 29 +++-- baya/tests/test_dynamic_roles.py | 20 ++-- baya/tests/test_integration.py | 145 +++++++++++------------ baya/tests/test_mock_ldap_helpers.py | 100 ++++++++-------- baya/tests/test_nodes.py | 51 +++++---- baya/tests/test_permissions.py | 145 +++++++++++------------ baya/tests/test_templatetags.py | 8 +- baya/tests/test_visitors.py | 164 +++++++++++++-------------- requirements-dev.txt | 9 +- tox.ini | 17 ++- 16 files changed, 427 insertions(+), 419 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e7b621d..e5cf7e3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -2.1.0: Add support for django 4.0, 4.1. Add support for Python 3.10, 3.11. +2.1.0: Add support for django 4.0, 4.1. Add support for Python 3.10, 3.11, 3.12 2.0.3: remove upper bound on django requirement 2.0.2: Bump py, flake8 and other dependencies for security. 2.0.0: Support for django 2.0, 2.1, 2.2. Add support for Python3.7. Drop support for Python 2.7 diff --git a/Makefile b/Makefile index d9f015a..6364c92 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ WITH_VENV=. $(VENV_ACTIVATE); ifdef TRAVIS_PYTHON_VERSION PYTHON=python$(TRAVIS_PYTHON_VERSION) else - PYTHON=python3.9 + PYTHON=python3.10 endif ifdef TOX_ENV @@ -84,3 +84,25 @@ dist: venv .PHONY: sdist sdist: dist @echo "runs dist" + +### Infastructure for Github Actions +.PHONY: ci-libs +ci-libs: + sudo apt-get update -y + sudo apt-get install -y libldap2-dev libssl-dev libsasl2-dev + +.PHONY: ci-install +ci-install: ci-libs venv + +.PHONY: ci-lint +ci-lint: lint + +.PHONY: ci-test +ci-test: test + +.PHONY: ci-version +ci-version: version + +.PHONY: ci-publish +ci-publish: + $(WITH_VENV) python setup.py sdist \ No newline at end of file diff --git a/baya/permissions.py b/baya/permissions.py index 1168e36..6284656 100644 --- a/baya/permissions.py +++ b/baya/permissions.py @@ -2,7 +2,7 @@ try: from collections.abc import Callable -except: +except Exception: from collections import Callable diff --git a/baya/tests/settings.py b/baya/tests/settings.py index 7b29ea1..654f042 100644 --- a/baya/tests/settings.py +++ b/baya/tests/settings.py @@ -21,7 +21,6 @@ 'django.contrib.auth', 'django.contrib.sessions', 'django.contrib.contenttypes', - 'django_nose', 'baya', 'baya.tests', 'baya.tests.submod', @@ -82,8 +81,6 @@ STATIC_URL = '/static/' -TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' - CSRF_USE_SESSIONS = False MIDDLEWARE = ( @@ -129,3 +126,5 @@ ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)" ) + +USE_TZ = False diff --git a/baya/tests/test_admin.py b/baya/tests/test_admin.py index 2865da2..3a4a510 100644 --- a/baya/tests/test_admin.py +++ b/baya/tests/test_admin.py @@ -1,4 +1,5 @@ from django.contrib.admin.options import InlineModelAdmin +import pytest from baya import RolesNode as g from baya.admin.sites import NestedGroupsAdminSite @@ -15,15 +16,16 @@ from unittest.mock import MagicMock +@pytest.mark.django_db class TestAdminSite(LDAPGroupAuthTestBase): def test_module_perms(self): app_label = Blag._meta.app_label for user in ['has_all', 'has_a', 'has_aa', 'has_aaa']: request = self.mock_get_request(self.login(user)) - self.assertTrue(request.user.has_module_perms(app_label)) + assert request.user.has_module_perms(app_label) request = self.mock_get_request(self.login('has_b')) - self.assertFalse(request.user.has_module_perms(app_label)) + assert not request.user.has_module_perms(app_label) def test_required_baya_groups(self): # The required groups for an admin site is the `or`-union of all @@ -32,7 +34,7 @@ def test_required_baya_groups(self): exp = ((g('AAA') & ALLOW_ALL) | (g('AA') & ALLOW_ALL) | (g('AA') | g('B'))) - self.assertEqual(required_groups, exp) + assert required_groups == exp def test_required_baya_groups_repeats(self): """Repeated roles should only be shown once.""" @@ -52,81 +54,80 @@ def test_required_baya_groups_repeats(self): site = NestedGroupsAdminSite() required_groups = site._get_required_baya_groups() exp = g('A') - self.assertEqual(required_groups, exp) + assert required_groups == exp def test_index(self): """Only display those apps which the user can access.""" request = self.mock_get_request(self.login('has_all')) index = site.index(request) app_list = index.context_data['app_list'] - self.assertEqual(len(app_list), 2) + assert len(app_list) == 2 for app in app_list: models = {str(model['name']) for model in app['models']} if len(models) == 2: - self.assertEqual({"Blags", "Entries"}, models) + assert {"Blags", "Entries"} == models for model in app['models']: for permission in ['add', 'change', 'delete']: - self.assertTrue(model['perms'][permission]) + assert model['perms'][permission] else: - self.assertEqual({"Comments"}, models) + assert {"Comments"} == models model = app['models'][0] - self.assertTrue(model['perms']['add']) - self.assertTrue(model['perms']['change']) - self.assertFalse(model['perms']['delete']) + assert model['perms']['add'] + assert model['perms']['change'] + assert not model['perms']['delete'] def test_read_only(self): # has_aaa can only access the read-only Blag changelist request = self.mock_get_request(self.login('has_aaa')) index = site.index(request) app_list = index.context_data['app_list'] - self.assertEqual(len(app_list), 1) + assert len(app_list) == 1 app_list = app_list[0] - self.assertEqual( - {"Blags"}, - {str(model['name']) for model in app_list['models']}) + assert {"Blags"} == {str(model['name']) for model in app_list['models']} perms = app_list['models'][0]['perms'] - self.assertFalse(perms['add']) - self.assertTrue(perms['change']) - self.assertFalse(perms['delete']) + assert not perms['add'] + assert perms['change'] + assert not perms['delete'] +@pytest.mark.django_db class TestOptions(LDAPGroupAuthTestBase): def _get_options(self): return site._registry[Blag] def test_add_permissions(self): options = self._get_options() - self.assertTrue( + assert ( options.has_add_permission( self.mock_get_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_add_permission( self.mock_get_request(self.login('has_a')))) - self.assertFalse( + assert not ( options.has_add_permission( self.mock_get_request(self.login('has_aaa')))) def test_change_view_permission(self): options = self._get_options() - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_a')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_aaa')))) def test_delete_permission(self): options = self._get_options() - self.assertTrue( + assert ( options.has_delete_permission( self.mock_post_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_delete_permission( self.mock_post_request(self.login('has_a')))) - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_post_request(self.login('has_aaa')))) @@ -137,19 +138,19 @@ def _get_options(self): def test_create_permissions(self): options = self._get_options() - self.assertTrue( + assert ( options.has_add_permission( self.mock_get_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_add_permission( self.mock_get_request(self.login('has_a')))) - self.assertFalse( + assert not ( options.has_add_permission( self.mock_get_request(self.login('has_aa')))) - self.assertFalse( + assert not ( options.has_add_permission( self.mock_get_request(self.login('has_aaa')))) - self.assertFalse( + assert not ( options.has_add_permission( self.mock_get_request(self.login('has_b')))) @@ -158,62 +159,63 @@ def test_read_permissions(self): # Note - django admin doesn't distinguish between read and update, so # baya blocks read-only access from writing, but it still looks to # the admin like they have change permissions. - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_a')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_aa')))) - self.assertFalse( + assert not ( options.has_change_permission( self.mock_get_request(self.login('has_aaa')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_b')))) def test_update_permissions(self): options = self._get_options() - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_all')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_a')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_aa')))) - self.assertFalse( + assert not ( options.has_change_permission( self.mock_get_request(self.login('has_aaa')))) - self.assertTrue( + assert ( options.has_change_permission( self.mock_get_request(self.login('has_b')))) def test_delete_permissions(self): options = self._get_options() - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_get_request(self.login('has_all')))) - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_get_request(self.login('has_a')))) - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_get_request(self.login('has_aa')))) - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_get_request(self.login('has_aaa')))) - self.assertFalse( + assert not ( options.has_delete_permission( self.mock_get_request(self.login('has_b')))) +@pytest.mark.django_db class TestInlines(LDAPGroupAuthTestBase): - def setUp(self): - super(TestInlines, self).setUp() + def setup_method(self): + super().setup_method() Blag.objects.all().delete() self.blag = Blag.objects.create(name="My Blag") self.entries = [ @@ -230,19 +232,16 @@ def _get_inlines(self): def test_entries_displayed(self): inline_formsets = self._get_inlines() - self.assertEqual(len(inline_formsets), 2) + assert len(inline_formsets) == 2 # The UnprotectedPhotoBlagEntryInline should not be here inline_opts = {type(inf.opts) for inf in inline_formsets} - self.assertEqual( - inline_opts, {BlagEntryInline, ProtectedPhotoBlagEntryInline}) + assert inline_opts == {BlagEntryInline, ProtectedPhotoBlagEntryInline} def test_perms_correct(self): def _check(inline, request, add, change, delete): - self.assertEqual(inline.opts.has_add_permission(request, obj=None), add) - self.assertEqual( - inline.opts.has_change_permission(request), change) - self.assertEqual( - inline.opts.has_delete_permission(request), delete) + assert inline.opts.has_add_permission(request, obj=None) == add + assert inline.opts.has_change_permission(request) == change + assert inline.opts.has_delete_permission(request) == delete inline_formsets = self._get_inlines() while inline_formsets: @@ -261,7 +260,7 @@ def _check(inline, request, add, change, delete): def test_inline_decoration(self): # This should fail because inlines don't have any {add,change,delete} # views to protect. - with self.assertRaises(TypeError): + with pytest.raises(TypeError): @requires(g('A')) class MyInline(InlineModelAdmin): pass diff --git a/baya/tests/test_backend.py b/baya/tests/test_backend.py index a21052d..d8a78a5 100644 --- a/baya/tests/test_backend.py +++ b/baya/tests/test_backend.py @@ -12,7 +12,7 @@ class TestReconnectingLDAP(TestCase): def test_getattr_not_initialize(self): ldap = Mock() reconnecting_ldap = ReconnectingLDAP(ldap) - self.assertIs(reconnecting_ldap.not_initialize, ldap.not_initialize) + assert reconnecting_ldap.not_initialize is ldap.not_initialize def test_initialize(self): ldap = Mock() @@ -30,8 +30,8 @@ class TestBackend(NestedLDAPGroupsBackend): def test_reconnecting_backend(self): backend = self.TestBackend() ldap_module = backend.ldap - self.assertTrue(isinstance(ldap_module, ReconnectingLDAP)) - self.assertIs(ldap_module.SERVER_DOWN, ldap.SERVER_DOWN) + assert isinstance(ldap_module, ReconnectingLDAP) + assert ldap_module.SERVER_DOWN is ldap.SERVER_DOWN class TestNonReconnectingLDAPBackend(TestCase): @@ -42,5 +42,5 @@ class TestBackend(NestedLDAPGroupsBackend): def test_non_reconnecting_backend(self): backend = self.TestBackend() ldap_module = backend.ldap - self.assertFalse(isinstance(ldap_module, ReconnectingLDAP)) - self.assertIs(ldap_module.SERVER_DOWN, ldap.SERVER_DOWN) + assert not isinstance(ldap_module, ReconnectingLDAP) + assert ldap_module.SERVER_DOWN is ldap.SERVER_DOWN diff --git a/baya/tests/test_base.py b/baya/tests/test_base.py index 210efe7..4010981 100644 --- a/baya/tests/test_base.py +++ b/baya/tests/test_base.py @@ -1,4 +1,5 @@ from unittest.mock import MagicMock +import pytest import django from django_auth_ldap import backend @@ -7,7 +8,7 @@ from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied from django.middleware.csrf import _get_new_csrf_string -from django.test import TestCase + if django.VERSION[:2] <= (2, 2): from django.middleware.csrf import _salt_cipher_secret @@ -20,26 +21,27 @@ from ..mock_ldap_helpers import mock_ldap_setup -class LDAPGroupAuthTestBase(TestCase): +@pytest.mark.django_db +class LDAPGroupAuthTestBase(): @classmethod - def setUpClass(cls): + def setup_class(cls): cls.mockldap = mock_ldap_setup( ldap_dc='dc=test', extra_users=directory.test_users, group_lineage=directory.group_lineage) @classmethod - def tearDownClass(cls): + def teardown_class(cls): del cls.mockldap - def setUp(self): + def setup_method(self): self.mockldap.start() self.ldapobj = self.mockldap['ldap://localhost'] self.backend = backend.LDAPBackend() self.backend.ldap # Force global configuration - def tearDown(self): + def teardown_method(self): self.mockldap.stop() del self.ldapobj @@ -88,11 +90,13 @@ def mock_post_request(self, *args, **kwargs): def assert_no_get_permission(self, user, view, get=None): request = self.mock_get_request(user, get=get) - self.assertRaises(PermissionDenied, view, request) + with pytest.raises(PermissionDenied): + view(request) def assert_no_post_permission(self, user, view, get=None, post=None): request = self.mock_post_request(user, get=get, post=post) - self.assertRaises(PermissionDenied, view, request) + with pytest.raises(PermissionDenied): + view(request) def assert_no_permission(self, user, view, get=None, post=None): self.assert_no_get_permission(user, view, get) @@ -101,18 +105,19 @@ def assert_no_permission(self, user, view, get=None, post=None): def assert_has_get_permission(self, user, view, get=None): request = self.mock_get_request(user, get=get) response = view(request) - self.assertEqual(response.status_code, 200) + assert response.status_code == 200 def assert_has_post_permission(self, user, view, get=None, post=None): request = self.mock_post_request(user, get=get, post=post) response = view(request) - self.assertEqual(response.status_code, 200) + assert response.status_code == 200 def assert_has_permission(self, user, view, get=None, post=None): self.assert_has_get_permission(user, view, get) self.assert_has_post_permission(user, view, get, post) +@pytest.mark.django_db class TestSetup(LDAPGroupAuthTestBase): def test_has_all_groups(self): """Verify that mockldap & django-auth-ldap are both working. @@ -123,5 +128,5 @@ def test_has_all_groups(self): group_count = Group.objects.count() self.login('has_all') group_count_2 = Group.objects.count() - self.assertGreater(group_count_2, group_count) - self.assertEqual(group_count_2 - group_count, 6) + assert group_count_2 > group_count + assert group_count_2 - group_count == 6 diff --git a/baya/tests/test_dynamic_roles.py b/baya/tests/test_dynamic_roles.py index a4f9e9e..8684013 100644 --- a/baya/tests/test_dynamic_roles.py +++ b/baya/tests/test_dynamic_roles.py @@ -26,21 +26,21 @@ def build_mock_request(self, request_group): def test_returns_set(self): """The formatter should return a set of groups.""" roles = self.formatter(self.build_mock_request('mygroup')) - self.assertEqual(type(roles), set) - self.assertEqual(len(roles), 1) - self.assertEqual(roles.pop(), "mygroup_admin") + assert type(roles) == set + assert len(roles) == 1 + assert roles.pop() == "mygroup_admin" def test_query_param(self): request = self.build_mock_request('mygroup') roles = self.formatter(request) - self.assertEqual(roles, {'mygroup_admin'}) + assert roles == {'mygroup_admin'} def test_reverse_kwarg(self): request = self.build_mock_request('mygroup') request.GET = {} request.resolver_match.kwargs = {'group': 'mygroup'} roles = self.formatter(request) - self.assertEqual(roles, {'mygroup_admin'}) + assert roles == {'mygroup_admin'} def test_query_param_collision(self): """The URL kwarg should take precedence over the query parameter.""" @@ -48,14 +48,14 @@ def test_query_param_collision(self): request.resolver_match.kwargs = {'group': 'kwarg_group'} with patch('baya.dynamic_roles.logger') as mock_logger: roles = self.formatter(request) - self.assertEqual(mock_logger.warning.call_count, 1) - self.assertEqual(roles, {'kwarg_group_admin'}) + assert mock_logger.warning.call_count == 1 + assert roles == {'kwarg_group_admin'} def test_str(self): st = str(self.formatter) - self.assertIn("%s_admin", st) - self.assertIn("group", st) + assert "%s_admin" in st + assert "group" in st def test_repr(self): re = repr(self.formatter) - self.assertIn(self.formatter.__class__.__name__, re) + assert self.formatter.__class__.__name__ in re diff --git a/baya/tests/test_integration.py b/baya/tests/test_integration.py index d2220cc..a2367b9 100644 --- a/baya/tests/test_integration.py +++ b/baya/tests/test_integration.py @@ -1,8 +1,9 @@ -from distutils.version import StrictVersion +import pytest -from django import get_version as get_django_version +from pytest_django.asserts import assertRedirects, assertContains, assertNotContains from django.urls import reverse from django.test.utils import override_settings +from django.test import client as dj_client from baya.tests.test_base import LDAPGroupAuthTestBase from baya.tests.models import Blag @@ -23,10 +24,9 @@ class _IntegrationBase(LDAPGroupAuthTestBase): URL level, and the RF doesn't go through that. """ def get_client(self, username=None, password='password'): - client = self.client + client = dj_client.Client() if username: - self.assertTrue( - client.login(username=username, password=password)) + assert client.login(username=username, password=password) return client def _get_and_assert_access( @@ -35,26 +35,24 @@ def _get_and_assert_access( client = self.get_client(username) url = reverse(url_name, args=reverse_args, kwargs=reverse_kwargs) response = client.get(url) - self.assertEqual( - response.status_code, - target_status_code, - '%s != %s, %s' % (response.status_code, target_status_code, - message)) + assert response.status_code == target_status_code,\ + f"{response.status_code} != {target_status_code}, {message}" return response +@pytest.mark.django_db class TestIntegration(_IntegrationBase): def _test_login_redirect( self, url_name, username, target_status_code, login_url='login'): client = self.get_client() url = reverse(url_name) response = client.get(url) - self.assertRedirects( + assertRedirects( response, "%s?next=%s" % (reverse(login_url), url)) login_response = client.post( response['Location'], {'username': username, 'password': 'password'}) - self.assertRedirects( + assertRedirects( login_response, url, target_status_code=target_status_code) client.logout() @@ -73,16 +71,14 @@ def test_verbs(self): def _has_method(client, method): verb = getattr(client, method) response = verb(url) - self.assertEqual( - response.status_code, OK, - "Error %s: %s not allowed" % (response.status_code, method)) + assert response.status_code == OK,\ + "Error %s: %s not allowed" % (response.status_code, method) def _has_not_method(client, method): verb = getattr(client, method) response = verb(url) - self.assertEqual( - response.status_code, DENIED, - "Error %s: %s allowed" % (response.status_code, method)) + assert response.status_code == DENIED,\ + "Error %s: %s allowed" % (response.status_code, method) url = reverse('my_view') @@ -105,7 +101,7 @@ def _has_not_method(client, method): def test_index(self): blag = Blag.objects.create(name="my blag") response = self._get_and_assert_access('index', 'has_all', OK) - self.assertContains(response, blag.name) + assertContains(response, blag.name) def test_my_view_str(self): """Test a decorated view method works when resolved by string path.""" @@ -199,19 +195,19 @@ def test_query_param(self): 'query_param_view', 'has_aa', OK, reverse_kwargs={'name': 'aa'}) +@pytest.mark.django_db class TestAdminIntegration(_IntegrationBase): def test_admin_view_uses_baya(self): # Default django admin_view returns a 200, not a 403 client = self.get_client('has_nothing') url = reverse('admin:index') response = client.get(url) - self.assertEqual(response.status_code, 403) + assert response.status_code == 403 # Ensure that baya_requires was set on the request - self.assertTrue(hasattr(response.context['request'], 'baya_requires')) + assert hasattr(response.context['request'], 'baya_requires') # And that it's in the 403 template - self.assertIn( - "{aaa} & True | {aa} & True | {aa} | {b}", - response.content.decode('utf-8')) + assert ("{aaa} & True | {aa} & True | {aa} | {b}" + in response.content.decode('utf-8')) def test_index(self): for url, reverse_kwargs in [ @@ -219,18 +215,18 @@ def test_index(self): ('admin:app_list', {'app_label': 'tests'})]: response = self._get_and_assert_access( url, 'has_all', OK, reverse_kwargs=reverse_kwargs) - self.assertContains(response, 'Blags') - self.assertContains(response, 'Entries') + assertContains(response, 'Blags') + assertContains(response, 'Entries') if 'index' in url: - self.assertContains(response, 'Comments') + assertContains(response, 'Comments') else: - self.assertNotContains(response, 'Comments') + assertNotContains(response, 'Comments') response = self._get_and_assert_access( url, 'has_aaa', OK, reverse_kwargs=reverse_kwargs) - self.assertContains(response, 'Blags') - self.assertNotContains(response, 'Entries') - self.assertNotContains(response, 'Comments') + assertContains(response, 'Blags') + assertNotContains(response, 'Entries') + assertNotContains(response, 'Comments') if 'index' in url: # B just sees an empty admin page, following the normal @@ -238,20 +234,12 @@ def test_index(self): response = self._get_and_assert_access( url, 'has_b', OK, reverse_kwargs=reverse_kwargs, message=url) - self.assertNotContains(response, 'Blags') - self.assertNotContains(response, 'Entries') - self.assertContains(response, 'Comments') + assertNotContains(response, 'Blags') + assertNotContains(response, 'Entries') + assertContains(response, 'Comments') else: - # In django <1.7 >1.10 B gets a 404 for app_list. - # In django >=1.7 <=1.10 B get sa 403, like you'd expect. - django_version = StrictVersion(get_django_version()) - if (django_version >= StrictVersion('1.7.0') and - django_version < StrictVersion('1.11.0')): - expected_status = DENIED - else: - expected_status = NOT_FOUND response = self._get_and_assert_access( - url, 'has_b', expected_status, + url, 'has_b', NOT_FOUND, reverse_kwargs=reverse_kwargs, message=url) @@ -280,13 +268,13 @@ def test_add(self): data = self._get_form_data() data.update({'name': 'has_all blag'}) response = client.post(add_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual(Blag.objects.count(), blag_count + 1) + assertRedirects(response, changelist_url) + assert Blag.objects.count() == blag_count + 1 # And the POST is rejected too client = self.get_client('has_aaa') response = client.post(add_url, {'name': 'has_aaa blag'}) - self.assertEqual(response.status_code, DENIED) - self.assertEqual(Blag.objects.count(), blag_count + 1) + assert response.status_code == DENIED + assert Blag.objects.count() == blag_count + 1 def test_changelist_view(self): self._get_and_assert_access( @@ -309,7 +297,7 @@ def test_read_not_update(self): client = self.get_client('has_b') response = client.post( change_url, {'id': '%s' % comment.id, 'body': 'syke'}) - self.assertEqual(response.status_code, DENIED) + assert response.status_code == DENIED def test_changelist_post(self): changelist_url = reverse('admin:tests_blag_changelist') @@ -326,13 +314,13 @@ def test_changelist_post(self): # But AAA can't actually change anything client = self.get_client('has_aaa') response = client.post(changelist_url, delete_kwargs) - self.assertEqual(response.status_code, DENIED) - self.assertEqual(Blag.objects.count(), blag_count) + assert response.status_code == DENIED + assert Blag.objects.count() == blag_count client = self.get_client('has_all') response = client.post(changelist_url, delete_kwargs) - self.assertRedirects(response, changelist_url) - self.assertEqual(Blag.objects.count(), blag_count - 1) + assertRedirects(response, changelist_url) + assert Blag.objects.count() == blag_count - 1 def test_change_view(self): blag = Blag.objects.create(name="blagonet") @@ -358,14 +346,14 @@ def test_change_post(self): 'name': 'new name', }) response = client.post(change_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual(Blag.objects.get(id=blag.id).name, 'new name') + assertRedirects(response, changelist_url) + assert Blag.objects.get(id=blag.id).name == 'new name' # ...but AAA Cannot actually change anything client = self.get_client('has_aaa') response = client.post( change_url, {'id': '%s' % blag.id, 'name': 'newer name'}) - self.assertEqual(response.status_code, DENIED) + assert response.status_code == DENIED def test_delete_view(self): blag = Blag.objects.create(name="blagonet") @@ -391,24 +379,25 @@ def test_delete_post(self): # ...but AAA Cannot actually change anything client = self.get_client('has_aaa') response = client.post(delete_url, data) - self.assertEqual(response.status_code, DENIED) + assert response.status_code == DENIED client = self.get_client('has_all') response = client.post(delete_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual(Blag.objects.count(), 0) + assertRedirects(response, changelist_url) + assert Blag.objects.count() == 0 def test_inner_url(self): """Should be able to decorate urls in ModelAdmin.get_urls().""" blag1 = Blag.objects.create(name='blag one') blag2 = Blag.objects.create(name='blag two') response = self._get_and_assert_access('admin:list', 'has_all', OK) - self.assertContains(response, blag1.name) - self.assertContains(response, blag2.name) + assertContains(response, blag1.name) + assertContains(response, blag2.name) self._get_and_assert_access('admin:list', 'has_aaa', DENIED) self._get_and_assert_access('admin:list', 'has_b', DENIED) +@pytest.mark.django_db class TestAdminInlineIntegration(_IntegrationBase): def _get_form_data(self): return { @@ -423,7 +412,7 @@ def _get_form_data(self): def test_add(self): blag = Blag.objects.create(name="blagonet") PhotoBlagEntry.objects.all().delete() - self.assertEqual(PhotoBlagEntry.objects.all().count(), 0) + assert PhotoBlagEntry.objects.all().count() == 0 change_url = reverse('admin:tests_blag_change', args=[blag.id]) changelist_url = reverse('admin:tests_blag_changelist') @@ -436,15 +425,14 @@ def test_add(self): # B has no permissions client = self.get_client('has_b') response = client.post(change_url, data) - self.assertEqual(response.status_code, 403) + assert response.status_code == 403 # A succeedes client = self.get_client('has_a') response = client.post(change_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual( - Blag.objects.get(id=blag.id).photoblagentry_set.count(), 1) - self.assertEqual(PhotoBlagEntry.objects.all().count(), 1) + assertRedirects(response, changelist_url) + assert Blag.objects.get(id=blag.id).photoblagentry_set.count() == 1 + assert PhotoBlagEntry.objects.all().count() == 1 def test_change(self): blag = Blag.objects.create(name="blagonet") @@ -453,8 +441,7 @@ def test_change(self): change_url = reverse('admin:tests_blag_change', args=[blag.id]) changelist_url = reverse('admin:tests_blag_changelist') - self.assertEqual( - Blag.objects.get(id=blag.id).photoblagentry_set.count(), 1) + assert Blag.objects.get(id=blag.id).photoblagentry_set.count() == 1 data = self._get_form_data() data.update({ @@ -468,17 +455,16 @@ def test_change(self): # B has no permissions client = self.get_client('has_b') response = client.post(change_url, data) - self.assertEqual(response.status_code, 403) + assert response.status_code == 403 # A successfully alters the entry client = self.get_client('has_a') - self.assertContains(client.get(change_url), entry.title) + assertContains(client.get(change_url), entry.title) response = client.post(change_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual( - Blag.objects.get(id=blag.id).photoblagentry_set.count(), 1) - self.assertEqual(PhotoBlagEntry.objects.all().count(), 1) - self.assertEqual(PhotoBlagEntry.objects.get().title, 'my new title') + assertRedirects(response, changelist_url) + assert Blag.objects.get(id=blag.id).photoblagentry_set.count() == 1 + assert PhotoBlagEntry.objects.all().count() == 1 + assert PhotoBlagEntry.objects.get().title == 'my new title' def test_delete(self): blag = Blag.objects.create(name="blagonet") @@ -502,12 +488,11 @@ def test_delete(self): # B has no permissions client = self.get_client('has_b') response = client.post(change_url, data) - self.assertEqual(response.status_code, 403) + assert response.status_code == 403 # A successfully deletes the entry client = self.get_client('has_a') response = client.post(change_url, data) - self.assertRedirects(response, changelist_url) - self.assertEqual( - Blag.objects.get(id=blag.id).photoblagentry_set.count(), 0) - self.assertEqual(PhotoBlagEntry.objects.all().count(), 0) + assertRedirects(response, changelist_url) + assert Blag.objects.get(id=blag.id).photoblagentry_set.count() == 0 + assert PhotoBlagEntry.objects.all().count() == 0 diff --git a/baya/tests/test_mock_ldap_helpers.py b/baya/tests/test_mock_ldap_helpers.py index 0dc7f63..b6450da 100644 --- a/baya/tests/test_mock_ldap_helpers.py +++ b/baya/tests/test_mock_ldap_helpers.py @@ -12,28 +12,25 @@ class TestPerson(TestCase): def test_attrs(self): name = "bigfoot" person_attrs = person(name) - self.assertEqual(person_attrs[0], - "cn=%s,ou=people,%s" % (name, DEFAULT_DC)) - self.assertEqual(person_attrs[1]['uid'], [name]) - self.assertEqual(person_attrs[1]['cn'], [name]) - self.assertEqual(person_attrs[1]['sn'], [name]) - self.assertEqual(person_attrs[1]['mail'], ["%s@test" % name]) + assert person_attrs[0] == "cn=%s,ou=people,%s" % (name, DEFAULT_DC) + assert person_attrs[1]['uid'] == [name] + assert person_attrs[1]['cn'] == [name] + assert person_attrs[1]['sn'] == [name] + assert person_attrs[1]['mail'] == ["%s@test" % name] def test_password(self): name = "yeti" person_attrs = person(name) - self.assertEqual(person_attrs[1]['userPassword'], ['password']) + assert person_attrs[1]['userPassword'] == ['password'] person_attrs = person(name, password='snowstorm') - self.assertEqual(person_attrs[1]['userPassword'], ['snowstorm']) + assert person_attrs[1]['userPassword'] == ['snowstorm'] def test_email(self): name = "sasquatch" dc = "dc=test,dc=example,dc=com" person_attrs = person(name, dc=dc) - self.assertEqual(person_attrs[0], - "cn=%s,ou=people,%s" % (name, dc)) - self.assertEqual(person_attrs[1]['mail'], - ["%s@test.example.com" % name]) + assert person_attrs[0] == "cn=%s,ou=people,%s" % (name, dc) + assert person_attrs[1]['mail'] == ["%s@test.example.com" % name] class TestGroup(TestCase): @@ -41,7 +38,7 @@ def test_attrs(self): member = person('bigfoot') name = "north-american-great-apes" group_attrs = group(name, member) - self.assertEqual(group_attrs[1]['cn'], [name]) + assert group_attrs[1]['cn'] == [name] class TestMockLdapDirectory(TestCase): @@ -60,68 +57,65 @@ def test_child_group_no_user(self): ], ldap_dc="", ) - self.assertEqual(len(directory), 12) - self.assertIn(group_dn('child_1', ""), directory) - self.assertEqual(directory[group_dn('child_1', '')]['memberOf'], - [group_dn('child_1_1', '')]) - self.assertEqual(directory[group_dn('child_1', "")]['member'], - [group_dn('the_parent', '')]) - self.assertIn(group_dn('child_2', ""), directory) - self.assertEqual( - directory[group_dn('child_2', '')]['memberOf'], - [group_dn('child_2_1', ''), group_dn('child_2_2', '')]) - self.assertEqual(directory[group_dn('child_2', "")]['member'], - [group_dn('the_parent', '')]) - self.assertIn(group_dn('child_1_1', ""), directory) - self.assertEqual(directory[group_dn('child_1_1', "")]['memberOf'], []) - self.assertEqual(directory[group_dn('child_1_1', "")]['member'], - [group_dn('child_1', '')]) - self.assertIn(group_dn('child_2_1', ""), directory) - self.assertEqual(directory[group_dn('child_2_1', "")]['memberOf'], []) - self.assertEqual(directory[group_dn('child_2_1', "")]['member'], - [group_dn('child_2', '')]) - self.assertIn(group_dn('child_2_2', ""), directory) - self.assertEqual(directory[group_dn('child_2_2', "")]['memberOf'], []) - self.assertEqual(directory[group_dn('child_2_2', "")]['member'], - [group_dn('child_2', '')]) + assert len(directory) == 12 + assert group_dn('child_1', "") in directory + assert (directory[group_dn('child_1', '')]['memberOf'] == + [group_dn('child_1_1', '')]) + assert (directory[group_dn('child_1', "")]['member'] == + [group_dn('the_parent', '')]) + assert group_dn('child_2', "") in directory + assert (directory[group_dn('child_2', '')]['memberOf'] == + [group_dn('child_2_1', ''), group_dn('child_2_2', '')]) + assert (directory[group_dn('child_2', "")]['member'] == + [group_dn('the_parent', '')]) + assert group_dn('child_1_1', "") in directory + assert directory[group_dn('child_1_1', "")]['memberOf'] == [] + assert (directory[group_dn('child_1_1', "")]['member'] == + [group_dn('child_1', '')]) + assert group_dn('child_2_1', "") in directory + assert directory[group_dn('child_2_1', "")]['memberOf'] == [] + assert (directory[group_dn('child_2_1', "")]['member'] == + [group_dn('child_2', '')]) + assert group_dn('child_2_2', "") in directory + assert directory[group_dn('child_2_2', "")]['memberOf'] == [] + assert (directory[group_dn('child_2_2', "")]['member'] == + [group_dn('child_2', '')]) def test_no_args(self): directory = mock_ldap_directory() - self.assertEqual(len(directory), 5) - self.assertSetEqual( - set(directory.keys()), - { - 'ou=Access,dc=example,dc=com', - 'dc=example,dc=com', - 'ou=Service-Accounts,dc=example,dc=com', - 'cn=auth,ou=people,dc=example,dc=com', - 'ou=People,dc=example,dc=com' - }) + assert len(directory) == 5 + assert (set(directory.keys()) == { + 'ou=Access,dc=example,dc=com', + 'dc=example,dc=com', + 'ou=Service-Accounts,dc=example,dc=com', + 'cn=auth,ou=people,dc=example,dc=com', + 'ou=People,dc=example,dc=com' + }) def test_bind_user(self): directory = mock_ldap_directory(ldap_dc="") dn = person_dn('auth', "") - self.assertIn(dn, directory) - self.assertEqual(directory[dn]['userPassword'], ['password']) + assert dn in directory + assert directory[dn]['userPassword'] == ['password'] def test_bind_password(self): directory = mock_ldap_directory( bind_user='ned', default_password='mancy', ldap_dc="") dn = person_dn('ned', "") - self.assertEqual(directory[dn]['userPassword'], ['password']) + assert directory[dn]['userPassword'] == ['password'] directory = mock_ldap_directory( bind_user='ned', bind_password='flanders', default_password='mancy', ldap_dc="") - self.assertEqual(directory[dn]['userPassword'], ['flanders']) + assert directory[dn]['userPassword'] == ['flanders'] def test_default_password(self): dn = person_dn('somebody', "") directory = mock_ldap_directory( ldap_dc="", extra_users=[('somebody', 'agroup')]) - self.assertEqual(directory[dn]['userPassword'], ['password']) + assert directory[dn]['userPassword'] == ['password'] directory = mock_ldap_directory( ldap_dc="", extra_users=[('somebody', 'agroup')], default_password='swordfish') - self.assertEqual(directory[dn]['userPassword'], ['swordfish']) + assert directory[dn]['userPassword'] == ['swordfish'] diff --git a/baya/tests/test_nodes.py b/baya/tests/test_nodes.py index f24f7d8..3d1faea 100644 --- a/baya/tests/test_nodes.py +++ b/baya/tests/test_nodes.py @@ -3,6 +3,7 @@ from operator import and_ from operator import or_ from operator import xor +import pytest from unittest import TestCase from ..membership import AndNode @@ -15,30 +16,34 @@ def test_equality(self): a = g('A') b = g('B') c = g('C') - self.assertNotEqual(a, b) - self.assertEqual(a & b, a & b) - self.assertNotEqual(a & b, a | b) - self.assertEqual((a & b) | c, (a & b | c)) - self.assertNotEqual(a & b, a | b) - self.assertNotEqual(a & b, a & b & c) + assert not a == b + assert a & b == a & b + assert not (a & b == a | b) + assert (a & b) | c == (a & b | c) + assert not (a & b == a | b) + assert not (a & b == a & b & c) def test_or_raises(self): """The or keyword is going to screw people up.""" - with self.assertRaises(TypeError): + with pytest.raises(TypeError): g('A') or g('B') def test_and_raises(self): """The and keyword is going to screw people up.""" - with self.assertRaises(TypeError): + with pytest.raises(TypeError): g('A') and g('B') def test_coercion(self): """Throw a TypeError when trying to combine nodes with non-nodes.""" for op in [and_, or_, xor]: - self.assertRaises(TypeError, op, g('A'), 'b') - self.assertRaises(TypeError, op, 'b', g('A')) - self.assertRaises(TypeError, op, g('A'), 1234) - self.assertRaises(TypeError, op, 1234, g('A')) + with pytest.raises(TypeError): + op(g('A'), 'b') + with pytest.raises(TypeError): + op('b', g('A')) + with pytest.raises(TypeError): + op(g('A'), 1234) + with pytest.raises(TypeError): + op(1234, g('A')) class TestDynamicRolesNode(TestCase): @@ -47,7 +52,7 @@ def test_get_roles_set(self): node = dg(roles_callable1) kwargs = {'a': 123} node.get_roles_set(**kwargs) - self.assertTrue(roles_callable1.called_with(**kwargs)) + assert roles_callable1.called_with(**kwargs) def test_get_roles_set_multiple_callables(self): roles_callable1 = Mock(return_value=set()) @@ -55,35 +60,35 @@ def test_get_roles_set_multiple_callables(self): node = dg(roles_callable1, roles_callable2) kwargs = {'b': 123} node.get_roles_set(**kwargs) - self.assertTrue(roles_callable1.called_with(**kwargs)) - self.assertTrue(roles_callable2.called_with(**kwargs)) + assert roles_callable1.called_with(**kwargs) + assert roles_callable2.called_with(**kwargs) def test_get_roles_set_or(self): c1 = lambda: {True} c2 = lambda: {True} c3 = lambda: {False} node = dg(c1, c2, c3) - self.assertEqual(node.get_roles_set(), {True, False}) + assert node.get_roles_set() == {True, False} def test_invalid_callable_return(self): c1 = lambda x: x node = dg(c1) - self.assertRaises(RuntimeError, node.get_roles_set, x='abc') + with pytest.raises(RuntimeError): + node.get_roles_set(x='abc') def test_combine_roles(self): """Combining roles into a simpler node when AND-ing.""" role1 = dg(lambda x: x) role2 = dg(lambda y: y) combined = role1 & role2 - self.assertTrue(isinstance(combined, dg)) - self.assertLess(role1._roles_set, combined._roles_set) - self.assertLess(role2._roles_set, combined._roles_set) - self.assertEqual(role1._roles_set | role2._roles_set, - combined._roles_set) + assert isinstance(combined, dg) + assert role1._roles_set < combined._roles_set + assert role2._roles_set < combined._roles_set + assert role1._roles_set | role2._roles_set == combined._roles_set def test_combine_regular_role(self): """Combining with a regular node should just give an AndNode.""" role1 = g('abc') role2 = dg(lambda y: y) combined = role1 & role2 - self.assertTrue(isinstance(combined, AndNode)) + assert isinstance(combined, AndNode) diff --git a/baya/tests/test_permissions.py b/baya/tests/test_permissions.py index 2d13f8c..9a24910 100644 --- a/baya/tests/test_permissions.py +++ b/baya/tests/test_permissions.py @@ -2,6 +2,7 @@ from unittest.mock import patch from unittest.mock import sentinel from types import FunctionType +import pytest import django from django.conf import settings @@ -31,9 +32,10 @@ B = g('b') +@pytest.mark.django_db class TestGate(LDAPGroupAuthTestBase): - def setUp(self): - super(TestGate, self).setUp() + def setup_method(self): + super(TestGate, self).setup_method() self.has_all = self.login('has_all') self.request_has_all = self.mock_get_request(self.has_all) self.has_aaa = self.login('has_aaa') @@ -44,11 +46,11 @@ def _has_permissions(self, node, roles): def test_case_insensitive(self): """Groups should be case insensitive.""" - self.assertEqual(g('A'), g('a')) - self.assertTrue(self._has_permissions(g('A'), ['A'])) - self.assertTrue(self._has_permissions(g('A'), ['a'])) - self.assertTrue(self._has_permissions(g('a'), ['A'])) - self.assertTrue(self._has_permissions(g('a'), ['a'])) + assert g('A') == g('a') + assert self._has_permissions(g('A'), ['A']) + assert self._has_permissions(g('A'), ['a']) + assert self._has_permissions(g('a'), ['A']) + assert self._has_permissions(g('a'), ['a']) def _test_perms(self, gate, has_all_perm, has_aaa_perm, method=None): if method == 'get': @@ -57,10 +59,8 @@ def _test_perms(self, gate, has_all_perm, has_aaa_perm, method=None): perm = 'has_post_permission' else: perm = 'has_any_permission' - self.assertEqual(getattr(gate, perm)(self.request_has_all), - has_all_perm) - self.assertEqual(getattr(gate, perm)(self.request_has_aaa), - has_aaa_perm) + assert getattr(gate, perm)(self.request_has_all) == has_all_perm + assert getattr(gate, perm)(self.request_has_aaa) == has_aaa_perm def test_no_permissions(self): """If no permissions declared, always allow.""" @@ -148,31 +148,30 @@ def test_all_and_get_and_post_requires(self): self._test_perms(gate, True, True, 'get') self._test_perms(gate, True, False, 'post') self._test_perms(gate, True, True) - self.assertFalse(gate.get_requires is gate.post_requires) + assert gate.get_requires is not gate.post_requires def test_redirect(self): g1 = Gate() - self.assertEqual(g1.login_url, settings.BAYA_LOGIN_URL) + assert g1.login_url == settings.BAYA_LOGIN_URL g2 = Gate(login_url=None) - self.assertEqual(g2.login_url, settings.BAYA_LOGIN_URL) + assert g2.login_url == settings.BAYA_LOGIN_URL custom_login = "/testlogin/" g3 = Gate(login_url=custom_login) - self.assertEqual(g3.login_url, custom_login) - self.assertEqual(str((g3 + g2).login_url), - str(custom_login)) - self.assertEqual((g2 + g3).login_url, custom_login) + assert g3.login_url == custom_login + assert str((g3 + g2).login_url) == str(custom_login) + assert (g2 + g3).login_url == custom_login with override_settings(BAYA_LOGIN_URL="/testlogin/"): g4 = Gate() - self.assertEqual(g4.login_url, "/testlogin/") + assert g4.login_url == "/testlogin/" with override_settings(BAYA_LOGIN_URL=None): g5 = Gate() - self.assertEqual(g5.login_url, "/login/") + assert g5.login_url == "/login/" def test_lazy_login_url(self): lazy_login_url = reverse_lazy('lazy_login') gate = Gate(login_url=lazy_login_url) - self.assertEqual(gate.login_url, lazy_login_url) - self.assertEqual(str(gate.login_url), '/lazy_login/') + assert gate.login_url == lazy_login_url + assert str(gate.login_url) == '/lazy_login/' def test_non_existent_group(self): """If you require a non-existent group, then nobody can authorize.""" @@ -182,24 +181,25 @@ def test_non_existent_group(self): self._test_perms(gate, False, False) +@pytest.mark.django_db class TestDeniedReason(LDAPGroupAuthTestBase): def test_not_logged_in(self): gate = Gate() request = self.mock_get_request() data = gate.get_permissions_required_data(request) - self.assertEqual(data['requires_groups'], g()) - self.assertEqual(data['requires_groups_str'], "{}") - self.assertEqual(data['user_groups'], []) - self.assertEqual(data['user_groups_str'], "{}") + assert data['requires_groups'] == g() + assert data['requires_groups_str'] == "{}" + assert data['user_groups'] == [] + assert data['user_groups_str'] == "{}" def test_insufficient_permissions(self): gate = Gate(AA | A) request = self.mock_get_request(self.login('has_aaa')) data = gate.get_permissions_required_data(request) - self.assertEqual(data['requires_groups'], AA | A) - self.assertEqual(data['requires_groups_str'], "{aa} | {a}") - self.assertEqual(data['user_groups'], ['aaa']) - self.assertEqual(data['user_groups_str'], "{aaa}") + assert data['requires_groups'] == AA | A + assert data['requires_groups_str'] == "{aa} | {a}" + assert data['user_groups'] == ['aaa'] + assert data['user_groups_str'] == "{aaa}" class MyListView(ListView): @@ -219,11 +219,11 @@ class TestRequires(LDAPGroupAuthTestBase): def test_str(self): """If given a string, convert to a PermissionNode.""" req = requires('a') - self.assertEqual(req.gate.get_requires, A) + assert req.gate.get_requires == A req = requires(['a', 'b']) - self.assertEqual(req.gate.get_requires, A & B) + assert req.gate.get_requires == A & B req = requires('a, b') - self.assertEqual(req.gate.get_requires, A & B) + assert req.gate.get_requires == A & B def test_no_denied_not_logged_in(self): """A user can access unprotected views when not logged in.""" @@ -239,8 +239,8 @@ def test_no_collision(self): """Multiple requires calls in different URLs shouldn't interact.""" call1 = requires(AA)(undecorated_view) call2 = requires(B)(undecorated_view) - self.assertFalse(hasattr(undecorated_view, '_gate')) - self.assertNotEqual(call1._gate, call2._gate) + assert not hasattr(undecorated_view, '_gate') + assert not call1._gate == call2._gate self.assert_no_permission(self.login('has_aaa'), call1) self.assert_no_permission(self.login('has_b'), call1) @@ -255,10 +255,10 @@ def test_no_collision(self): def test_url_wrapping_syntax(self): """Test the syntax for decorating a url pattern.""" decorated = requires(get=AA, post=g('nobody'))(undecorated_view) - self.assertTrue(hasattr(decorated, '_gate')) - self.assertTrue(isinstance(decorated._gate, Gate)) - self.assertEqual(type(decorated), FunctionType) - self.assertEqual(decorated._gate.get_requires, AA) + assert hasattr(decorated, '_gate') + assert isinstance(decorated._gate, Gate) + assert type(decorated) == FunctionType + assert decorated._gate.get_requires == AA self.assert_has_get_permission(self.login('has_aa'), decorated) self.assert_has_get_permission(self.login('has_all'), decorated) self.assert_no_get_permission(self.login('has_aaa'), decorated) @@ -268,9 +268,9 @@ def test_url_wrapping_syntax(self): def test_method_view_has_gate(self): """Test decorating a regular method view.""" - self.assertTrue(hasattr(my_view, '_gate')) - self.assertTrue(isinstance(my_view._gate, Gate)) - self.assertEqual(type(my_view), FunctionType) + assert hasattr(my_view, '_gate') + assert isinstance(my_view._gate, Gate) + assert type(my_view) == FunctionType exclude = requires(g('nobody'))(my_view) self.assert_has_get_permission(self.login('has_all'), my_view) self.assert_no_get_permission(self.login('has_all'), exclude) @@ -289,16 +289,17 @@ def test_method_view_has_gate(self): def test_class_view_fails(self): """Test decorating a CBV.""" - self.assertRaises(TypeError, requires(A), MyListView) + with pytest.raises(TypeError): + requires(A)(MyListView) def test_class_view_as_view_method(self): """Ensure that the as_view() method can be decorated.""" view = MyListView.as_view() decorated1 = requires(g('one'))(view) decorated2 = requires(g('two'))(view) - self.assertFalse(decorated1 is view) - self.assertTrue(hasattr(decorated1, '_gate')) - self.assertNotEqual(decorated1._gate, decorated2._gate) + assert decorated1 is not view + assert hasattr(decorated1, '_gate') + assert not decorated1._gate == decorated2._gate def test_functools_partial(self): """Test that a functools.partial is able to be decorated.""" @@ -310,14 +311,14 @@ def pseudoview(request, foo): decorated1 = requires(g('one'))(view) decorated2 = requires(g('two'))(view) - self.assertFalse(decorated1 is view) - self.assertTrue(hasattr(decorated1, '_gate')) - self.assertNotEqual(decorated1._gate, decorated2._gate) + assert decorated1 is not view + assert hasattr(decorated1, '_gate') + assert not decorated1._gate == decorated2._gate def test_multiple(self): # B is anded with the others decorated1 = requires(B, get=AAA, post=AA)(undecorated_view) - self.assertEqual(decorated1._gate.post_requires, B & AA) + assert decorated1._gate.post_requires == B & AA self.assert_no_get_permission(self.login('has_b'), decorated1) self.assert_no_post_permission(self.login('has_b'), decorated1) self.assert_no_get_permission(self.login('has_aaa'), decorated1) @@ -327,18 +328,18 @@ def test_multiple(self): decorated2 = requires(get=(AAA | B), post=(AA | B))( undecorated_view) - self.assertEqual(decorated2._gate.get_requires, AAA | B) - self.assertEqual(decorated2._gate.post_requires, AA | B) + assert decorated2._gate.get_requires == AAA | B + assert decorated2._gate.post_requires == AA | B decorated2 = requires(A, get=(AAA | B), post=(AA | B))( undecorated_view) - self.assertEqual(decorated2._gate.get_requires, A & (AAA | B)) - self.assertEqual(decorated2._gate.post_requires, A & (AA | B)) + assert decorated2._gate.get_requires == A & (AAA | B) + assert decorated2._gate.post_requires == A & (AA | B) def test_chaining(self): decorated1 = requires(A)(undecorated_view) decorated2 = requires(B)(decorated1) - self.assertNotEqual(decorated1._gate, decorated2._gate) + assert not decorated1._gate == decorated2._gate self.assert_has_permission(self.login('has_a'), decorated1) self.assert_no_permission(self.login('has_a'), decorated2) # B doesn't have access to either, because decorated1 still requires A @@ -351,38 +352,32 @@ def test_chain_user_has_permission(self): decorated1 = requires(A)(undecorated_view) decorated2 = requires(B)(decorated1) for perm in ['get', 'post', 'any']: - self.assertTrue( - has_permission(decorated1, self.login('has_a'), perm)) - self.assertFalse( - has_permission(decorated2, self.login('has_a'), perm)) - self.assertFalse( - has_permission(decorated1, self.login('has_b'), perm)) - self.assertFalse( - has_permission(decorated2, self.login('has_b'), perm)) - self.assertTrue( - has_permission(decorated1, self.login('has_a_b'), perm)) - self.assertTrue( - has_permission(decorated2, self.login('has_a_b'), perm)) + assert has_permission(decorated1, self.login('has_a'), perm) + assert not has_permission(decorated2, self.login('has_a'), perm) + assert not has_permission(decorated1, self.login('has_b'), perm) + assert not has_permission(decorated2, self.login('has_b'), perm) + assert has_permission(decorated1, self.login('has_a_b'), perm) + assert has_permission(decorated2, self.login('has_a_b'), perm) def test_redirect(self): url = "url" decorated = requires(B, get=AAA, post=AA)(undecorated_view) - self.assertEqual(decorated._gate.login_url, settings.LOGIN_URL) + assert decorated._gate.login_url == settings.LOGIN_URL decorated = requires(B, login_url=url, get=AAA, post=AA)( undecorated_view) - self.assertEqual(decorated._gate.login_url, url) + assert decorated._gate.login_url == url with patch('django.contrib.auth.views.redirect_to_login', return_value=sentinel) as do_redirect: request = self.mock_get_request() redirect = decorated(request) do_redirect.assert_called_once_with(request.get_full_path(), url) - self.assertIs(redirect, sentinel) + assert redirect is sentinel def test_str_view_path(self): """Test decorating a string path to a view throws an exception.""" - self.assertRaises( - TypeError, requires(A), 'baya.tests.views.my_view') + with pytest.raises(TypeError): + requires(A)('baya.tests.views.my_view') def test_include(self): """Make sure requires(A)(include(my_app.urls)) works.""" @@ -391,10 +386,8 @@ def test_include(self): [cell] = [cell for cell in pattern.resolve.__closure__ if isinstance(cell.cell_contents, requires)] requirer = cell.cell_contents - self.assertTrue( - PermissionChecker(['a']).visit(requirer.gate.get_requires)) - self.assertTrue( - PermissionChecker(['a']).visit(requirer.gate.post_requires)) + assert PermissionChecker(['a']).visit(requirer.gate.get_requires) + assert PermissionChecker(['a']).visit(requirer.gate.post_requires) def test_deny_all(self): def _no_perms(method): diff --git a/baya/tests/test_templatetags.py b/baya/tests/test_templatetags.py index ffed95a..7c25970 100644 --- a/baya/tests/test_templatetags.py +++ b/baya/tests/test_templatetags.py @@ -1,9 +1,11 @@ +import pytest from django.template import Context from django.template import Template from .test_base import LDAPGroupAuthTestBase from django.contrib.auth.models import AnonymousUser +@pytest.mark.django_db class CanUserPerformActionTagTest(LDAPGroupAuthTestBase): BASIC_TEMPLATE = Template( @@ -22,7 +24,7 @@ def test_anonymous_user_has_permission_false(self): 'user': AnonymousUser(), }) rendered = self.BASIC_TEMPLATE.render(context) - self.assertIn('False', rendered) + assert 'False' in rendered def test_has_permission_false(self): context = Context({ @@ -30,7 +32,7 @@ def test_has_permission_false(self): 'user': self.login('has_nothing'), }) rendered = self.BASIC_TEMPLATE.render(context) - self.assertIn('False', rendered) + assert 'False' == rendered def test_has_permission_true(self): context = Context({ @@ -38,4 +40,4 @@ def test_has_permission_true(self): 'user': self.login('has_all'), }) rendered = self.BASIC_TEMPLATE.render(context) - self.assertIn('True', rendered) + assert 'True' in rendered diff --git a/baya/tests/test_visitors.py b/baya/tests/test_visitors.py index 862562f..82258a6 100644 --- a/baya/tests/test_visitors.py +++ b/baya/tests/test_visitors.py @@ -1,5 +1,5 @@ from unittest.mock import MagicMock -from unittest import TestCase +import pytest from ..dynamic_roles import DjangoRequestGroupFormatter from ..membership import DynamicRolesNode as dg @@ -9,8 +9,9 @@ from ..visitors import PermissionChecker -class TestPermissionChecker(TestCase): - def setUp(self): +@pytest.mark.django_db +class TestPermissionChecker(): + def setup_method(self): self.a = g('A') self.b = g('B') self.c = g('C') @@ -32,139 +33,130 @@ def _has_permissions(self, node, roles, **kwargs): return PermissionChecker(roles).visit(node, **kwargs) def test_set_membership_single(self): - self.assertTrue(self._has_permissions(self.a, ['A'])) - self.assertFalse(self._has_permissions(self.a, ['B'])) + assert self._has_permissions(self.a, ['A']) + assert not self._has_permissions(self.a, ['B']) def test_and(self): and_node = self.a & self.b - self.assertTrue(self._has_permissions(and_node, ['A', 'B'])) - self.assertFalse(self._has_permissions(and_node, ['A'])) - self.assertFalse(self._has_permissions(and_node, ['B'])) + assert self._has_permissions(and_node, ['A', 'B']) + assert not self._has_permissions(and_node, ['A']) + assert not self._has_permissions(and_node, ['B']) def test_and_dynamic(self): """Ensure the group permissions are using the requested group.""" and_node = self.a & self.s_admin - self.assertTrue(self._has_permissions( - and_node, ['A', 'a_admin'], request=self.mock_request('A'))) - self.assertFalse(self._has_permissions( - and_node, ['A', 'a_admin'], request=self.mock_request('B'))) + assert self._has_permissions( + and_node, ['A', 'a_admin'], request=self.mock_request('A')) + assert not self._has_permissions( + and_node, ['A', 'a_admin'], request=self.mock_request('B')) def test_or(self): or_node = self.a | self.b - self.assertTrue(self._has_permissions(or_node, ['A', 'B'])) - self.assertTrue(self._has_permissions(or_node, ['A'])) - self.assertTrue(self._has_permissions(or_node, ['B'])) - self.assertTrue(self._has_permissions(or_node, ['A', 'B', 'C'])) + assert self._has_permissions(or_node, ['A', 'B']) + assert self._has_permissions(or_node, ['A']) + assert self._has_permissions(or_node, ['B']) + assert self._has_permissions(or_node, ['A', 'B', 'C']) def test_xor(self): xor_node = self.a ^ self.b - self.assertFalse(self._has_permissions(xor_node, ['A', 'B'])) - self.assertTrue(self._has_permissions(xor_node, ['A'])) - self.assertTrue(self._has_permissions(xor_node, ['B'])) + assert not self._has_permissions(xor_node, ['A', 'B']) + assert self._has_permissions(xor_node, ['A']) + assert self._has_permissions(xor_node, ['B']) def test_not(self): not_node = ~self.a - self.assertFalse(self._has_permissions(not_node, ['A', 'B'])) - self.assertFalse(self._has_permissions(not_node, ['A'])) - self.assertTrue(self._has_permissions(not_node, ['B'])) - self.assertFalse(self._has_permissions(not_node, ['A', 'B', 'C'])) - self.assertTrue(self._has_permissions(not_node, ['B', 'C'])) + assert not self._has_permissions(not_node, ['A', 'B']) + assert not self._has_permissions(not_node, ['A']) + assert self._has_permissions(not_node, ['B']) + assert not self._has_permissions(not_node, ['A', 'B', 'C']) + assert self._has_permissions(not_node, ['B', 'C']) def test_and_or_and(self): node = (self.a & self.b) | (self.c & self.s_admin) req = self.mock_request('a') - self.assertFalse(self._has_permissions(node, ['A'], request=req)) - self.assertFalse(self._has_permissions(node, ['B'], request=req)) - self.assertFalse(self._has_permissions(node, ['C'], request=req)) - self.assertFalse( - self._has_permissions(node, ['a_admin'], request=req)) - self.assertTrue(self._has_permissions(node, ['A', 'B'], request=req)) - self.assertTrue( - self._has_permissions(node, ['a_admin', 'C'], request=req)) - self.assertFalse(self._has_permissions(node, ['A', 'C'], request=req)) - self.assertFalse( - self._has_permissions(node, ['B', 'a_admin'], request=req)) + assert not self._has_permissions(node, ['A'], request=req) + assert not self._has_permissions(node, ['B'], request=req) + assert not self._has_permissions(node, ['C'], request=req) + assert not self._has_permissions(node, ['a_admin'], request=req) + assert self._has_permissions(node, ['A', 'B'], request=req) + assert self._has_permissions(node, ['a_admin', 'C'], request=req) + assert not self._has_permissions(node, ['A', 'C'], request=req) + assert not self._has_permissions(node, ['B', 'a_admin'], request=req) def test_and_xor_not_and(self): """What a ridiculous membership requirement.""" node = (self.a & self.b) ^ ~(self.c | self.s_admin) req = self.mock_request('A') - self.assertTrue(self._has_permissions(node, ['A'], request=req)) - self.assertTrue(self._has_permissions(node, ['B'], request=req)) - self.assertFalse(self._has_permissions(node, ['C'], request=req)) - self.assertFalse(self._has_permissions(node, ['a_admin'], request=req)) - self.assertFalse(self._has_permissions(node, ['A', 'B'], request=req)) - self.assertFalse( - self._has_permissions(node, ['a_admin', 'C'], request=req)) - self.assertFalse(self._has_permissions(node, ['A', 'C'], request=req)) - self.assertFalse( - self._has_permissions(node, ['B', 'a_admin'], request=req)) - self.assertTrue(self._has_permissions( - node, ['A', 'B', 'a_admin'], request=req)) - self.assertTrue(self._has_permissions( - node, ['A', 'B', 'C'], request=req)) - self.assertTrue(self._has_permissions( - node, ['A', 'B', 'C', 'a_admin'], request=req)) + assert self._has_permissions(node, ['A'], request=req) + assert self._has_permissions(node, ['B'], request=req) + assert not self._has_permissions(node, ['C'], request=req) + assert not self._has_permissions(node, ['a_admin'], request=req) + assert not self._has_permissions(node, ['A', 'B'], request=req) + assert not self._has_permissions(node, ['a_admin', 'C'], request=req) + assert not self._has_permissions(node, ['A', 'C'], request=req) + assert not self._has_permissions(node, ['B', 'a_admin'], request=req) + assert self._has_permissions(node, ['A', 'B', 'a_admin'], request=req) + assert self._has_permissions(node, ['A', 'B', 'C'], request=req) + assert self._has_permissions(node, ['A', 'B', 'C', 'a_admin'], request=req) def test_value_node(self): node1 = ValueNode(True) node2 = ~ValueNode(False) - self.assertTrue(self._has_permissions(node1, ['A'])) - self.assertTrue(self._has_permissions(node2, ['A'])) - self.assertTrue(self._has_permissions(node1, [''])) - self.assertTrue(self._has_permissions(node2, [''])) - self.assertTrue(self._has_permissions(node1, ['A', 'F'])) - self.assertTrue(self._has_permissions(node2, ['A', 'F'])) + assert self._has_permissions(node1, ['A']) + assert self._has_permissions(node2, ['A']) + assert self._has_permissions(node1, ['']) + assert self._has_permissions(node2, ['']) + assert self._has_permissions(node1, ['A', 'F']) + assert self._has_permissions(node2, ['A', 'F']) node1 = ValueNode(False) node2 = ~ValueNode(True) - self.assertFalse(self._has_permissions(node1, ['A'])) - self.assertFalse(self._has_permissions(node2, ['A'])) - self.assertFalse(self._has_permissions(node1, [''])) - self.assertFalse(self._has_permissions(node2, [''])) - self.assertFalse(self._has_permissions(node1, ['A', 'F'])) - self.assertFalse(self._has_permissions(node2, ['A', 'F'])) + assert not self._has_permissions(node1, ['A']) + assert not self._has_permissions(node2, ['A']) + assert not self._has_permissions(node1, ['']) + assert not self._has_permissions(node2, ['']) + assert not self._has_permissions(node1, ['A', 'F']) + assert not self._has_permissions(node2, ['A', 'F']) def test_member_and_value_node(self): node = ValueNode(True) | g('A') - self.assertTrue(self._has_permissions(node, ['A'])) - self.assertTrue(self._has_permissions(node, [''])) - self.assertTrue(self._has_permissions(node, ['A', 'F'])) + assert self._has_permissions(node, ['A']) + assert self._has_permissions(node, ['']) + assert self._has_permissions(node, ['A', 'F']) node = ValueNode(True) & g('A') - self.assertTrue(self._has_permissions(node, ['A'])) - self.assertFalse(self._has_permissions(node, [''])) - self.assertTrue(self._has_permissions(node, ['A', 'F'])) + assert self._has_permissions(node, ['A']) + assert not self._has_permissions(node, ['']) + assert self._has_permissions(node, ['A', 'F']) node = ValueNode(False) | g('A') - self.assertTrue(self._has_permissions(node, ['A'])) - self.assertFalse(self._has_permissions(node, [''])) - self.assertTrue(self._has_permissions(node, ['A', 'F'])) + assert self._has_permissions(node, ['A']) + assert not self._has_permissions(node, ['']) + assert self._has_permissions(node, ['A', 'F']) node = ValueNode(False) & g('A') - self.assertFalse(self._has_permissions(node, ['A'])) - self.assertFalse(self._has_permissions(node, [''])) - self.assertFalse(self._has_permissions(node, ['A', 'F'])) + assert not self._has_permissions(node, ['A']) + assert not self._has_permissions(node, ['']) + assert not self._has_permissions(node, ['A', 'F']) -class TestExpressionWriter(TestCase): - def setUp(self): +@pytest.mark.django_db +class TestExpressionWriter(): + def setup_method(self): self.writer = ExpressionWriter() def test_operator_precedence(self): node = g('A') ^ g('B') | g('C') ^ g('D') - self.assertEqual('{a} ^ {b} | {c} ^ {d}', self.writer.visit(node), - repr(node)) + assert '{a} ^ {b} | {c} ^ {d}', self.writer.visit(node) == repr(node) node = ~(g('A') & g('B')) ^ (g('C') | g('D') & g('E')) - self.assertEqual('~{a, b} ^ ({c} | {d, e})', self.writer.visit(node), - repr(node)) + assert '~{a, b} ^ ({c} | {d, e})', self.writer.visit(node) == repr(node) def test_unary(self): node = ~~g('A') - self.assertEqual('~~{a}', self.writer.visit(node), repr(node)) + assert '~~{a}', self.writer.visit(node) == repr(node) node = ~(g('A') ^ g('B')) - self.assertEqual('~({a} ^ {b})', self.writer.visit(node), repr(node)) + assert '~({a} ^ {b})', self.writer.visit(node) == repr(node) def test_value_node(self): node = ~ValueNode(True) - self.assertEqual('~True', self.writer.visit(node)) + assert '~True' == self.writer.visit(node) node = g('A') & ValueNode(False) - self.assertEqual('{a} & False', self.writer.visit(node)) + assert '{a} & False' == self.writer.visit(node) node = ~node - self.assertEqual('~({a} & False)', self.writer.visit(node)) + assert '~({a} & False)' == self.writer.visit(node) diff --git a/requirements-dev.txt b/requirements-dev.txt index f1a51c6..b1bebc0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,8 +1,11 @@ -coverage==5.1 -django-nose==1.4.6 +coverage funcparserlib==0.3.6 mockldap==0.2.6 -nose==1.3.7 pycodestyle==2.9.1 pyflakes==2.5.0 flake8==5.0.4 + +pytest==7.0.1 +py==1.11.0 +pytest-cov==3.0.0 +pytest-django==4.5.2 \ No newline at end of file diff --git a/tox.ini b/tox.ini index 4dd6293..3fd4554 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] install_command = pip install {opts} {packages} downloadcache = {toxworkdir}/_download/ -envlist = {py37}-django{3.1,3.2},{py38,py39,py310,py311}-django{3.1,3.2,4.0,4.1} +envlist = {py37}-django{3.1,3.2},{py38,py39,py310,py311}-django{3.1,3.2,4.0,4.1},p312-django{3.2,4.0,4.1} indexserver = default = https://pypi.python.org/simple @@ -9,9 +9,10 @@ indexserver = [testenv] setuptools_version = setuptools<58.0 usedevelop = True +setenv = + DJANGO_SETTINGS_MODULE=baya.tests.settings commands = - coverage run --omit="*tests*" --source=baya --branch \ - ./baya/tests/manage.py test {posargs:baya} + py.test {posargs:baya} deps = -r{toxinidir}/requirements-dev.txt django3.1: Django>=3.1,<3.2 @@ -25,11 +26,18 @@ whitelist_externals = flake8 commands = flake8 -v baya/ +[testenv:py311-django3.2] +commands = + rm -f .coverage + py.test --cov=baya {posargs:baya} [flake8] max-line-length = 99 ignore = E731,E402,W504 +[pytest] +DJANGO_SETTINGS_MODULE = baya.tests.settings +python_files = tests.py test_*.py *_tests.py [gh-actions] python = @@ -37,4 +45,5 @@ python = 3.8: py38 3.9: py39 3.10: py310 - 3.11: py311 \ No newline at end of file + 3.11: py311 + 3.12: py312 \ No newline at end of file