Skip to content

admin/files: fix get_objects_for_user queryset argument in FileUsedByView (cherry-pick #18845 to version-2025.10)#18846

Closed
authentik-automation[bot] wants to merge 1 commit intoversion-2025.10from
cherry-pick/18845-to-version-2025.10
Closed

admin/files: fix get_objects_for_user queryset argument in FileUsedByView (cherry-pick #18845 to version-2025.10)#18846
authentik-automation[bot] wants to merge 1 commit intoversion-2025.10from
cherry-pick/18845-to-version-2025.10

Conversation

@authentik-automation
Copy link
Contributor

⚠️ This cherry-pick has conflicts that require manual resolution.

Cherry-pick of #18845 to version-2025.10 branch.

Original PR: #18845
Original Author: @dominic-r
Cherry-picked commit: 26cfbe6

Please resolve the conflicts in this PR before merging.

This cherry-pick has conflicts that need manual resolution.

Original PR: #18845
Original commit: 26cfbe6
@netlify
Copy link

netlify bot commented Dec 16, 2025

Deploy Preview for authentik-docs canceled.

Name Link
🔨 Latest commit 358da23
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/6940aa5ad707bb00086dfb0c

@dominic-r dominic-r closed this Dec 16, 2025
@netlify
Copy link

netlify bot commented Dec 16, 2025

Deploy Preview for authentik-integrations ready!

Name Link
🔨 Latest commit 358da23
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/6940aa5aa7c8590008b0f090
😎 Deploy Preview https://deploy-preview-18846--authentik-integrations.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@dominic-r dominic-r deleted the cherry-pick/18845-to-version-2025.10 branch December 16, 2025 00:41
@codecov
Copy link

codecov bot commented Dec 16, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
77 1 76 2
View the top 1 failed test(s) by shortest run time
::authentik.admin.files.api
Stack Traces | 0s run time
path = PosixPath('.../admin/files/api.py')
config = <_pytest.config.Config object at 0x7f0a561570e0>

    def importtestmodule(
        path: Path,
        config: Config,
    ):
        # We assume we are only called once per module.
        importmode = config.getoption("--import-mode")
        try:
>           mod = import_path(
                path,
                mode=importmode,
                root=config.rootpath,
                consider_namespace_packages=config.getini("consider_namespace_packages"),
            )

.venv/lib/python3.13.............../site-packages/_pytest/python.py:493: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

path = PosixPath('.../admin/files/api.py')

    def import_path(
        path: str | os.PathLike[str],
        *,
        mode: str | ImportMode = ImportMode.prepend,
        root: Path,
        consider_namespace_packages: bool,
    ) -> ModuleType:
        """
        Import and return a module from the given path, which can be a file (a module) or
        a directory (a package).
    
        :param path:
            Path to the file to import.
    
        :param mode:
            Controls the underlying import mechanism that will be used:
    
            * ImportMode.prepend: the directory containing the module (or package, taking
              `__init__.py` files into account) will be put at the *start* of `sys.path` before
              being imported with `importlib.import_module`.
    
            * ImportMode.append: same as `prepend`, but the directory will be appended
              to the end of `sys.path`, if not already in `sys.path`.
    
            * ImportMode.importlib: uses more fine control mechanisms provided by `importlib`
              to import the module, which avoids having to muck with `sys.path` at all. It effectively
              allows having same-named test modules in different places.
    
        :param root:
            Used as an anchor when mode == ImportMode.importlib to obtain
            a unique name for the module being imported so it can safely be stored
            into ``sys.modules``.
    
        :param consider_namespace_packages:
            If True, consider namespace packages when resolving module names.
    
        :raises ImportPathMismatchError:
            If after importing the given `path` and the module `__file__`
            are different. Only raised in `prepend` and `append` modes.
        """
        path = Path(path)
        mode = ImportMode(mode)
    
        if not path.exists():
            raise ImportError(path)
    
        if mode is ImportMode.importlib:
            # Try to import this module using the standard import mechanisms, but
            # without touching sys.path.
            try:
                pkg_root, module_name = resolve_pkg_root_and_module_name(
                    path, consider_namespace_packages=consider_namespace_packages
                )
            except CouldNotResolvePathError:
                pass
            else:
                # If the given module name is already in sys.modules, do not import it again.
                with contextlib.suppress(KeyError):
                    return sys.modules[module_name]
    
                mod = _import_module_using_spec(
                    module_name, path, pkg_root, insert_modules=False
                )
                if mod is not None:
                    return mod
    
            # Could not import the module with the current sys.path, so we fall back
            # to importing the file as a single module, not being a part of a package.
            module_name = module_name_from_path(path, root)
            with contextlib.suppress(KeyError):
                return sys.modules[module_name]
    
>           mod = _import_module_using_spec(
                module_name, path, path.parent, insert_modules=True
            )

.venv/lib/python3.13............/site-packages/_pytest/pathlib.py:561: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

module_name = 'authentik.admin.files.api'
module_path = PosixPath('.../admin/files/api.py')
module_location = PosixPath('.../authentik/admin/files')

    def _import_module_using_spec(
        module_name: str, module_path: Path, module_location: Path, *, insert_modules: bool
    ) -> ModuleType | None:
        """
        Tries to import a module by its canonical name, path, and its parent location.
    
        :param module_name:
            The expected module name, will become the key of `sys.modules`.
    
        :param module_path:
            The file path of the module, for example `.../foo/bar/test_demo.py`.
            If module is a package, pass the path to the  `__init__.py` of the package.
            If module is a namespace package, pass directory path.
    
        :param module_location:
            The parent location of the module.
            If module is a package, pass the directory containing the `__init__.py` file.
    
        :param insert_modules:
            If True, will call `insert_missing_modules` to create empty intermediate modules
            with made-up module names (when importing test files not reachable from `sys.path`).
    
        Example 1 of parent_module_*:
    
            module_name:        "a.b.c.demo"
            module_path:        Path(".../b/c/demo.py")
            module_location:    Path("a/b/c/")
            if "a.b.c" is package (".../b/c/__init__.py" exists), then
                parent_module_name:         "a.b.c"
                parent_module_path:         Path(".../b/c/__init__.py")
                parent_module_location:     Path("a/b/c/")
            else:
                parent_module_name:         "a.b.c"
                parent_module_path:         Path("a/b/c")
                parent_module_location:     Path("a/b/")
    
        Example 2 of parent_module_*:
    
            module_name:        "a.b.c"
            module_path:        Path(".../b/c/__init__.py")
            module_location:    Path("a/b/c/")
            if  "a.b" is package ("a/b/__init__.py" exists), then
                parent_module_name:         "a.b"
                parent_module_path:         Path("a/b/__init__.py")
                parent_module_location:     Path("a/b/")
            else:
                parent_module_name:         "a.b"
                parent_module_path:         Path("a/b/")
                parent_module_location:     Path("a/")
        """
        # Attempt to import the parent module, seems is our responsibility:
        # https://github..../Lib/importlib/_bootstrap.py#L1308-L1311
        parent_module_name, _, name = module_name.rpartition(".")
        parent_module: ModuleType | None = None
        if parent_module_name:
            parent_module = sys.modules.get(parent_module_name)
            # If the parent_module lacks the `__path__` attribute, AttributeError when finding a submodule's spec,
            # requiring re-import according to the path.
            need_reimport = not hasattr(parent_module, "__path__")
            if parent_module is None or need_reimport:
                # Get parent_location based on location, get parent_path based on path.
                if module_path.name == "__init__.py":
                    # If the current module is in a package,
                    # need to leave the package first and then enter the parent module.
                    parent_module_path = module_path.parent.parent
                else:
                    parent_module_path = module_path.parent
    
                if (parent_module_path / "__init__.py").is_file():
                    # If the parent module is a package, loading by  __init__.py file.
                    parent_module_path = parent_module_path / "__init__.py"
    
                parent_module = _import_module_using_spec(
                    parent_module_name,
                    parent_module_path,
                    parent_module_path.parent,
                    insert_modules=insert_modules,
                )
    
        # Checking with sys.meta_path first in case one of its hooks can import this module,
        # such as our own assertion-rewrite hook.
        for meta_importer in sys.meta_path:
            module_name_of_meta = getattr(meta_importer.__class__, "__module__", "")
            if module_name_of_meta == "_pytest.assertion.rewrite" and module_path.is_file():
                # Import modules in subdirectories by module_path
                # to ensure assertion rewrites are not missed (#12659).
                find_spec_path = [str(module_location), str(module_path)]
            else:
                find_spec_path = [str(module_location)]
    
            spec = meta_importer.find_spec(module_name, find_spec_path)
    
            if spec_matches_module_path(spec, module_path):
                break
        else:
            loader = None
            if module_path.is_dir():
                # The `spec_from_file_location` matches a loader based on the file extension by default.
                # For a namespace package, need to manually specify a loader.
                loader = NamespaceLoader(name, module_path, PathFinder())
    
            spec = importlib.util.spec_from_file_location(
                module_name, str(module_path), loader=loader
            )
    
        if spec_matches_module_path(spec, module_path):
            assert spec is not None
            # Find spec and import this module.
            mod = importlib.util.module_from_spec(spec)
            sys.modules[module_name] = mod
>           spec.loader.exec_module(mod)  # type: ignore[union-attr]

.venv/lib/python3.13............/site-packages/_pytest/pathlib.py:725: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_frozen_importlib_external.SourceFileLoader object at 0x7f0a54de2ab0>
module = <module 'authentik.admin.files.api' from '.../admin/files/api.py'>

>   ???

<frozen importlib._bootstrap_external>:1023: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

f = <built-in function exec>
args = (<code object <module> at 0x5584991b7110, file ".../admin/files/api.py", l...harField': <class 'rest_framework.fields.CharField'>, 'ChoiceField': <class 'rest_framework.fields.ChoiceField'>, ...})
kwds = {}

>   ???

<frozen importlib._bootstrap>:488: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    import mimetypes
    
    from django.db.models import Q
    from django.utils.translation import gettext as _
    from drf_spectacular.utils import extend_schema
    from guardian.shortcuts import get_objects_for_user
    from rest_framework.exceptions import ValidationError
    from rest_framework.fields import BooleanField, CharField, ChoiceField, FileField
    from rest_framework.parsers import MultiPartParser
    from rest_framework.permissions import SAFE_METHODS
    from rest_framework.request import Request
    from rest_framework.response import Response
    from rest_framework.views import APIView
    
>   from authentik.admin.files.fields import FileField as AkFileField
E   ModuleNotFoundError: No module named 'authentik.admin.files.fields'

.../admin/files/api.py:15: ModuleNotFoundError

The above exception was the direct cause of the following exception:

cls = <class '_pytest.runner.CallInfo'>
func = <function pytest_make_collect_report.<locals>.collect at 0x7f0a54d27ce0>
when = 'collect', reraise = (<class 'KeyboardInterrupt'>, <class 'SystemExit'>)

    @classmethod
    def from_call(
        cls,
        func: Callable[[], TResult],
        when: Literal["collect", "setup", "call", "teardown"],
        reraise: type[BaseException] | tuple[type[BaseException], ...] | None = None,
    ) -> CallInfo[TResult]:
        """Call func, wrapping the result in a CallInfo.
    
        :param func:
            The function to call. Called without arguments.
        :type func: Callable[[], _pytest.runner.TResult]
        :param when:
            The phase in which the function is called.
        :param reraise:
            Exception or exceptions that shall propagate if raised by the
            function, instead of being wrapped in the CallInfo.
        """
        excinfo = None
        start = timing.time()
        precise_start = timing.perf_counter()
        try:
>           result: TResult | None = func()

.venv/lib/python3.13....../site-packages/_pytest/runner.py:341: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def collect() -> list[Item | Collector]:
        # Before collecting, if this is a Directory, load the conftests.
        # If a conftest import fails to load, it is considered a collection
        # error of the Directory collector. This is why it's done inside of the
        # CallInfo wrapper.
        #
        # Note: initial conftests are loaded early, not here.
        if isinstance(collector, Directory):
            collector.config.pluginmanager._loadconftestmodules(
                collector.path,
                collector.config.getoption("importmode"),
                rootpath=collector.config.rootpath,
                consider_namespace_packages=collector.config.getini(
                    "consider_namespace_packages"
                ),
            )
    
>       return list(collector.collect())

.venv/lib/python3.13....../site-packages/_pytest/runner.py:389: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <DoctestModule api.py>

    def collect(self) -> Iterable[DoctestItem]:
        import doctest
    
        class MockAwareDocTestFinder(doctest.DocTestFinder):
            py_ver_info_minor = sys.version_info[:2]
            is_find_lineno_broken = (
                py_ver_info_minor < (3, 11)
                or (py_ver_info_minor == (3, 11) and sys.version_info.micro < 9)
                or (py_ver_info_minor == (3, 12) and sys.version_info.micro < 3)
            )
            if is_find_lineno_broken:
    
                def _find_lineno(self, obj, source_lines):
                    """On older Pythons, doctest code does not take into account
                    `@property`. https://github..../cpython/issues/61648
    
                    Moreover, wrapped Doctests need to be unwrapped so the correct
                    line number is returned. #8796
                    """
                    if isinstance(obj, property):
                        obj = getattr(obj, "fget", obj)
    
                    if hasattr(obj, "__wrapped__"):
                        # Get the main obj in case of it being wrapped
                        obj = inspect.unwrap(obj)
    
                    # Type ignored because this is a private function.
                    return super()._find_lineno(  # type:ignore[misc]
                        obj,
                        source_lines,
                    )
    
            if sys.version_info < (3, 10):
    
                def _find(
                    self, tests, obj, name, module, source_lines, globs, seen
                ) -> None:
                    """Override _find to work around issue in stdlib.
    
                    https://github..../pytest/issues/3456
                    https://github..../cpython/issues/69718
                    """
                    if _is_mocked(obj):
                        return  # pragma: no cover
                    with _patch_unwrap_mock_aware():
                        # Type ignored because this is a private function.
                        super()._find(  # type:ignore[misc]
                            tests, obj, name, module, source_lines, globs, seen
                        )
    
            if sys.version_info < (3, 13):
    
                def _from_module(self, module, object):
                    """`cached_property` objects are never considered a part
                    of the 'current module'. As such they are skipped by doctest.
                    Here we override `_from_module` to check the underlying
                    function instead. https://github..../cpython/issues/107995
                    """
                    if isinstance(object, functools.cached_property):
                        object = object.func
    
                    # Type ignored because this is a private function.
                    return super()._from_module(module, object)  # type: ignore[misc]
    
        try:
>           module = self.obj

.venv/lib/python3.13.../site-packages/_pytest/doctest.py:566: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <DoctestModule api.py>

    @property
    def obj(self):
        """Underlying Python object."""
        obj = getattr(self, "_obj", None)
        if obj is None:
>           self._obj = obj = self._getobj()

.venv/lib/python3.13.............../site-packages/_pytest/python.py:284: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <DoctestModule api.py>

    def _getobj(self):
>       return importtestmodule(self.path, self.config)

.venv/lib/python3.13.............../site-packages/_pytest/python.py:546: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

path = PosixPath('.../admin/files/api.py')
config = <_pytest.config.Config object at 0x7f0a561570e0>

    def importtestmodule(
        path: Path,
        config: Config,
    ):
        # We assume we are only called once per module.
        importmode = config.getoption("--import-mode")
        try:
            mod = import_path(
                path,
                mode=importmode,
                root=config.rootpath,
                consider_namespace_packages=config.getini("consider_namespace_packages"),
            )
        except SyntaxError as e:
            raise nodes.Collector.CollectError(
                ExceptionInfo.from_current().getrepr(style="short")
            ) from e
        except ImportPathMismatchError as e:
            raise nodes.Collector.CollectError(
                "import file mismatch:\n"
                "imported module {!r} has this __file__ attribute:\n"
                "  {}\n"
                "which is not the same as the test file we want to collect:\n"
                "  {}\n"
                "HINT: remove __pycache__ / .pyc files and/or use a "
                "unique basename for your test file modules".format(*e.args)
            ) from e
        except ImportError as e:
            exc_info = ExceptionInfo.from_current()
            if config.get_verbosity() < 2:
                exc_info.traceback = exc_info.traceback.filter(filter_traceback)
            exc_repr = (
                exc_info.getrepr(style="short")
                if exc_info.traceback
                else exc_info.exconly()
            )
            formatted_tb = str(exc_repr)
>           raise nodes.Collector.CollectError(
                f"ImportError while importing test module '{path}'.\n"
                "Hint: make sure your test modules/packages have valid Python names.\n"
                "Traceback:\n"
                f"{formatted_tb}"
            ) from e
E           _pytest.nodes.Collector.CollectError: ImportError while importing test module '.../admin/files/api.py'.
E           Hint: make sure your test modules/packages have valid Python names.
E           Traceback:
E           .venv/lib/python3.13.............../site-packages/_pytest/python.py:493: in importtestmodule
E               mod = import_path(
E           .venv/lib/python3.13............/site-packages/_pytest/pathlib.py:561: in import_path
E               mod = _import_module_using_spec(
E           .venv/lib/python3.13............/site-packages/_pytest/pathlib.py:725: in _import_module_using_spec
E               spec.loader.exec_module(mod)  # type: ignore[union-attr]
E           <frozen importlib._bootstrap_external>:1023: in exec_module
E               ???
E           <frozen importlib._bootstrap>:488: in _call_with_frames_removed
E               ???
E           .../admin/files/api.py:15: in <module>
E               from authentik.admin.files.fields import FileField as AkFileField
E           E   ModuleNotFoundError: No module named 'authentik.admin.files.fields'

.venv/lib/python3.13.............../site-packages/_pytest/python.py:523: CollectError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant