Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ Unreleased

*

0.17.1 - 2025-11-14
********************

Fixed
=====

* Avoid circular import of AuthzEnforcer.

0.17.0 - 2025-11-14
********************

Expand Down
2 changes: 1 addition & 1 deletion openedx_authz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

import os

__version__ = "0.17.0"
__version__ = "0.17.1"

ROOT_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
4 changes: 3 additions & 1 deletion openedx_authz/engine/enforcer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from django.conf import settings

from openedx_authz.engine.adapter import ExtendedAdapter
from openedx_authz.engine.matcher import is_admin_or_superuser_check


def libraries_v2_enabled() -> bool:
Expand Down Expand Up @@ -201,6 +200,9 @@ def _initialize_enforcer(cls) -> SyncedEnforcer:
Returns:
SyncedEnforcer: Configured Casbin enforcer with adapter and auto-sync
"""
# Avoid circular import
from openedx_authz.engine.matcher import is_admin_or_superuser_check # pylint: disable=import-outside-toplevel

db_alias = getattr(settings, "CASBIN_DB_ALIAS", "default")

try:
Expand Down
36 changes: 36 additions & 0 deletions openedx_authz/tests/test_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Test module imports."""
import sys
from unittest import TestCase


class TestImports(TestCase):
"""Test that imports work correctly."""

def setUp(self):
"""Remove cached modules to ensure fresh imports and detect circular dependencies.
"""
super().setUp()

# List of modules to remove from cache to test fresh imports
modules_to_clear = [
'openedx_authz.engine.enforcer',
'openedx_authz.engine.matcher',
'openedx_authz.engine.adapter',
'openedx_authz.api',
'openedx_authz.api.permissions',
'openedx_authz.api.roles',
'openedx_authz.api.users',
'openedx_authz.api.data',
]

for module_name in modules_to_clear:
if module_name in sys.modules:
del sys.modules[module_name]

def test_import_authzenforcer(self):
"""Test that AuthzEnforcer can be imported."""
from openedx_authz.engine.enforcer import AuthzEnforcer # pylint: disable=import-outside-toplevel
try:
self.assertIsNotNone(AuthzEnforcer)
except ImportError as e:
self.fail(f"Failed to import AuthzEnforcer: {e}")