Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

root: replace poetry with uv #13388

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft

root: replace poetry with uv #13388

wants to merge 5 commits into from

Conversation

rissson
Copy link
Member

@rissson rissson commented Mar 4, 2025

Details

Just trying stuff out

In any case, this would be blocked by dependabot/dependabot-core#10478

Plus, it probably conflicts heavily with #12700


Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If an API change has been made

  • The API schema has been updated (make gen-build)

If changes to the frontend have been made

  • The code has been formatted (make web)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make website)

rissson added 3 commits March 4, 2025 18:04
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
@rissson rissson self-assigned this Mar 4, 2025
Copy link

netlify bot commented Mar 4, 2025

Deploy Preview for authentik-storybook canceled.

Name Link
🔨 Latest commit 1c5152e
🔍 Latest deploy log https://app.netlify.com/sites/authentik-storybook/deploys/67c743210809c500081b71a5

@rissson rissson changed the title wip root: replace poetry with uv Mar 4, 2025
Copy link

netlify bot commented Mar 4, 2025

Deploy Preview for authentik-docs canceled.

Name Link
🔨 Latest commit 1c5152e
🔍 Latest deploy log https://app.netlify.com/sites/authentik-docs/deploys/67c743212d3fce0008caef0f

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Copy link

codecov bot commented Mar 4, 2025

❌ 76 Tests Failed:

Tests completed Failed Passed Skipped
1718 76 1642 2
View the top 3 failed test(s) by shortest run time
authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI::test_create_transactional_bindings
Stack Traces | 0.611s run time
self = <unittest.case._Outcome object at 0x7ff08fe142c0>
test_case = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
result = <TestCaseFunction test_create_transactional_bindings>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
method = <bound method TestTransactionalApplicationsAPI.test_create_transactional_bindings of <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>

    def test_create_transactional_bindings(self):
        """Test transactional Application + provider creation"""
        assign_perm("authentik_policies.add_policybinding", self.user)
        self.client.force_login(self.user)
        uid = generate_id()
        group = Group.objects.create(name=generate_id())
        authorization_flow = create_test_flow()
>       response = self.client.put(
            reverse("authentik_api:core-transactional-application"),
            data={
                "app": {
                    "name": uid,
                    "slug": uid,
                },
                "provider_model": "authentik_providers_oauth2.oauth2provider",
                "provider": {
                    "name": uid,
                    "authorization_flow": str(authorization_flow.pk),
                    "invalidation_flow": str(authorization_flow.pk),
                    "redirect_uris": [],
                },
                "policy_bindings": [{"group": group.pk, "order": 0}],
            },
        )

.../core/tests/test_transactional_applications_api.py:81: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
path = '.../core/transactional/applications/'
data = {'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'slug': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf'}, 'pol...9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}
format = None, content_type = None, follow = False, extra = {}

    def put(self, path, data=None, format=None, content_type=None,
            follow=False, **extra):
>       response = super().put(
            path, data=data, format=format, content_type=content_type, **extra)

.venv/lib/python3.12.............../site-packages/rest_framework/test.py:303: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf","slug":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf"},"provid...b7eb-2ce0584101e5","redirect_uris":[]},"policy_bindings":[{"group":"29bdb447-6cdf-4263-b2c6-88ad3b37cf05","order":0}]}'
format = None, content_type = 'application/json', extra = {}

    def put(self, path, data=None, format=None, content_type=None, **extra):
        data, content_type = self._encode_data(data, format, content_type)
>       return self.generic('PUT', path, data, content_type, **extra)

.venv/lib/python3.12.............../site-packages/rest_framework/test.py:213: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>, method = 'PUT'
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf","slug":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf"},"provid...b7eb-2ce0584101e5","redirect_uris":[]},"policy_bindings":[{"group":"29bdb447-6cdf-4263-b2c6-88ad3b37cf05","order":0}]}'
content_type = 'application/json', secure = False
extra = {'CONTENT_TYPE': 'application/json'}

    def generic(self, method, path, data='',
                content_type='application/octet-stream', secure=False, **extra):
        # Include the CONTENT_TYPE, regardless of whether or not data is empty.
        if content_type is not None:
            extra['CONTENT_TYPE'] = str(content_type)
    
>       return super().generic(
            method, path, data, content_type, secure, **extra)

.venv/lib/python3.12.............../site-packages/rest_framework/test.py:233: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>, method = 'PUT'
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf","slug":"HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf"},"provid...b7eb-2ce0584101e5","redirect_uris":[]},"policy_bindings":[{"group":"29bdb447-6cdf-4263-b2c6-88ad3b37cf05","order":0}]}'
content_type = 'application/json', secure = False, headers = None
extra = {'CONTENT_TYPE': 'application/json'}
parsed = ParseResult(scheme='', netloc='', path='.../core/transactional/applications/', params='', query='', fragment='')
r = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}
query_string = ''

    def generic(
        self,
        method,
        path,
        data="",
        content_type="application/octet-stream",
        secure=False,
        *,
        headers=None,
        **extra,
    ):
        """Construct an arbitrary HTTP request."""
        parsed = urlparse(str(path))  # path can be lazy
        data = force_bytes(data, settings.DEFAULT_CHARSET)
        r = {
            "PATH_INFO": self._get_path(parsed),
            "REQUEST_METHOD": method,
            "SERVER_PORT": "443" if secure else "80",
            "wsgi.url_scheme": "https" if secure else "http",
        }
        if data:
            r.update(
                {
                    "CONTENT_LENGTH": str(len(data)),
                    "CONTENT_TYPE": content_type,
                    "wsgi.input": FakePayload(data),
                }
            )
        if headers:
            extra.update(HttpHeaders.to_wsgi_names(headers))
        r.update(extra)
        # If QUERY_STRING is absent or empty, we want to extract it from the URL.
        if not r.get("QUERY_STRING"):
            # WSGI requires latin-1 encoded strings. See get_path_info().
            query_string = parsed[4].encode().decode("iso-8859-1")
            r["QUERY_STRING"] = query_string
>       return self.request(**r)

.venv/lib/python3.12.../django/test/client.py:617: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
kwargs = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}

    def request(self, **kwargs):
        # Ensure that any credentials set get added to every request.
        kwargs.update(self._credentials)
>       return super().request(**kwargs)

.venv/lib/python3.12.............../site-packages/rest_framework/test.py:285: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
kwargs = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}

    def request(self, **kwargs):
>       request = super().request(**kwargs)

.venv/lib/python3.12.............../site-packages/rest_framework/test.py:237: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
request = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}
environ = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'HTTP_COOKIE': 'authentik_session=bgri80kghlyarzrbwclrcbuodteqeh48', 'PATH_INFO': '.../core/transactional/applications/', ...}
data = {}
on_template_render = functools.partial(<function store_rendered_templates at 0x7ff09a28bf60>, {})
signal_uid = 'template-render-140671179571072'
exception_uid = 'request-exception-140671179571072'
response = <HttpResponseNotAllowed [GET, HEAD, OPTIONS] status_code=405, "text/html; charset=utf-8">

    def request(self, **request):
        """
        Make a generic request. Compose the environment dictionary and pass
        to the handler, return the result of the handler. Assume defaults for
        the query environment, which can be overridden using the arguments to
        the request.
        """
        environ = self._base_environ(**request)
    
        # Curry a data dictionary into an instance of the template renderer
        # callback function.
        data = {}
        on_template_render = partial(store_rendered_templates, data)
        signal_uid = "template-render-%s" % id(request)
        signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid)
        # Capture exceptions created by the handler.
        exception_uid = "request-exception-%s" % id(request)
        got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid)
        try:
            response = self.handler(environ)
        finally:
            signals.template_rendered.disconnect(dispatch_uid=signal_uid)
            got_request_exception.disconnect(dispatch_uid=exception_uid)
        # Check for signaled exceptions.
>       self.check_exception(response)

.venv/lib/python3.12.../django/test/client.py:1013: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7ff08f6b45c0>
response = <HttpResponseNotAllowed [GET, HEAD, OPTIONS] status_code=405, "text/html; charset=utf-8">

    def check_exception(self, response):
        """
        Look for a signaled exception, clear the current context exception
        data, re-raise the signaled exception, and clear the signaled exception
        from the local cache.
        """
        response.exc_info = self.exc_info
        if self.exc_info:
            _, exc_value, _ = self.exc_info
            self.exc_info = None
            if self.raise_request_exception:
>               raise exc_value

.venv/lib/python3.12.../django/test/client.py:743: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>

    @wraps(get_response)
    def inner(request):
        try:
>           response = get_response(request)

.venv/lib/python3.12.../core/handlers/exception.py:55: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.ForceAuthClientHandler object at 0x7ff090063ef0>
request = <WSGIRequest: PUT '.../core/transactional/applications/'>

    def _get_response(self, request):
        """
        Resolve and call the view, then apply view, exception, and
        template_response middleware. This method is everything that happens
        inside the request/response middleware.
        """
        response = None
        callback, callback_args, callback_kwargs = self.resolve_request(request)
    
        # Apply view middleware
        for middleware_method in self._view_middleware:
            response = middleware_method(
                request, callback, callback_args, callback_kwargs
            )
            if response:
                break
    
        if response is None:
            wrapped_callback = self.make_view_atomic(callback)
            # If it is an asynchronous view, run it in a subthread.
            if iscoroutinefunction(wrapped_callback):
                wrapped_callback = async_to_sync(wrapped_callback)
            try:
>               response = wrapped_callback(request, *callback_args, **callback_kwargs)

.venv/lib/python3.12.../core/handlers/base.py:197: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
current_scope = <Scope id=0x7ff09cb8ef80 name=None type=ScopeType.CURRENT>
sentry_scope = <Scope id=0x7ff09c97af80 name=None type=ScopeType.ISOLATION>

    @functools.wraps(callback)
    def sentry_wrapped_callback(request, *args, **kwargs):
        # type: (Any, *Any, **Any) -> Any
        current_scope = sentry_sdk.get_current_scope()
        if current_scope.transaction is not None:
            current_scope.transaction.update_active_thread()
    
        sentry_scope = sentry_sdk.get_isolation_scope()
        # set the active thread id to the handler thread for sync views
        # this isn't necessary for async views since that runs on main
        if sentry_scope.profile is not None:
            sentry_scope.profile.update_active_thread_id()
    
        with sentry_sdk.start_span(
            op=OP.VIEW_RENDER,
            name=request.resolver_match.view_name,
            origin=DjangoIntegration.origin,
        ):
>           return callback(request, *args, **kwargs)

.venv/lib/python3.12.../integrations/django/views.py:94: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}

    def _view_wrapper(request, *args, **kwargs):
>       return view_func(request, *args, **kwargs)

.venv/lib/python3.12.../views/decorators/csrf.py:65: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        self.setup(request, *args, **kwargs)
        if not hasattr(self, "request"):
            raise AttributeError(
                "%s instance has no 'request' attribute. Did you override "
                "setup() and forget to call super()?" % cls.__name__
            )
>       return self.dispatch(request, *args, **kwargs)

.venv/lib/python3.12.../views/generic/base.py:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
handler = <bound method TransactionalApplicationView.put of <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>>

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
            response = handler(request, *args, **kwargs)
    
        except Exception as exc:
>           response = self.handle_exception(exc)

.venv/lib/python3.12............/site-packages/rest_framework/views.py:509: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>
exc = RelatedObjectDoesNotExist('PolicyBinding has no target.')

    def handle_exception(self, exc):
        """
        Handle any exception that occurs, by returning an appropriate response,
        or re-raising the error.
        """
        if isinstance(exc, (exceptions.NotAuthenticated,
                            exceptions.AuthenticationFailed)):
            # WWW-Authenticate header for 401 responses, else coerce to 403
            auth_header = self.get_authenticate_header(self.request)
    
            if auth_header:
                exc.auth_header = auth_header
            else:
                exc.status_code = status.HTTP_403_FORBIDDEN
    
        exception_handler = self.get_exception_handler()
    
        context = self.get_exception_handler_context()
        response = exception_handler(exc, context)
    
        if response is None:
>           self.raise_uncaught_exception(exc)

.venv/lib/python3.12............/site-packages/rest_framework/views.py:469: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>
exc = RelatedObjectDoesNotExist('PolicyBinding has no target.')

    def raise_uncaught_exception(self, exc):
        if settings.DEBUG:
            request = self.request
            renderer_format = getattr(request.accepted_renderer, 'format')
            use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
            request.force_plaintext_errors(use_plaintext_traceback)
>       raise exc

.venv/lib/python3.12............/site-packages/rest_framework/views.py:480: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
handler = <bound method TransactionalApplicationView.put of <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>>

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
>           response = handler(request, *args, **kwargs)

.venv/lib/python3.12............/site-packages/rest_framework/views.py:506: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7ff090061580>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>

    @extend_schema(
        request=TransactionApplicationSerializer(),
        responses={
            200: TransactionApplicationResponseSerializer(),
        },
    )
    def put(self, request: Request) -> Response:
        """Convert data into a blueprint, validate it and apply it"""
        data = TransactionApplicationSerializer(data=request.data)
>       data.is_valid(raise_exception=True)

.../core/api/transactional_applications.py:166: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'slug': 'HQ9yvLYf9Q...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.12.............../site-packages/rest_framework/serializers.py:223: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'slug': 'HQ9yvLYf9Q...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)
data = {'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'slug': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf'}, 'pol...9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
            self.run_validators(value)
>           value = self.validate(value)

.venv/lib/python3.12.............../site-packages/rest_framework/serializers.py:445: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'slug': 'HQ9yvLYf9Q...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)
attrs = {'app': {'name': 'HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'provider': <[EntryInvalidError('KeyOf: failed to find en...9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}

    def validate(self, attrs: dict) -> dict:
        blueprint = Blueprint()
        blueprint.entries.append(
            BlueprintEntry(
                model=attrs["provider_model"],
                state=BlueprintEntryDesiredState.MUST_CREATED,
                identifiers={
                    "name": attrs["provider"]["name"],
                },
                # Must match the name of the field on `self`
                id="provider",
                attrs=attrs["provider"],
            )
        )
        app_data = attrs["app"]
        app_data["provider"] = KeyOf(None, ScalarNode(tag="", value="provider"))
        blueprint.entries.append(
            BlueprintEntry(
                model="authentik_core.application",
                state=BlueprintEntryDesiredState.MUST_CREATED,
                identifiers={
                    "slug": attrs["app"]["slug"],
                },
                attrs=app_data,
                # Must match the name of the field on `self`
                id="app",
            )
        )
        for binding in attrs.get("policy_bindings", []):
            binding["target"] = KeyOf(None, ScalarNode(tag="", value="app"))
            for key, value in binding.items():
                if not isinstance(value, Model):
                    continue
                binding[key] = value.pk
            blueprint.entries.append(
                BlueprintEntry(
                    model="authentik_policies.policybinding",
                    state=BlueprintEntryDesiredState.MUST_CREATED,
                    identifiers=binding,
                )
            )
        importer = Importer(blueprint, {})
        try:
>           valid, _ = importer.validate(raise_validation_errors=True)

.../core/api/transactional_applications.py:133: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7ff08f9e1be0>
raise_validation_errors = True

    def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
        """Validate loaded blueprint export, ensure all models are allowed
        and serializers have no errors"""
        self.logger.debug("Starting blueprint import validation")
        orig_import = deepcopy(self._import)
        if self._import.version != 1:
            self.logger.warning("Invalid blueprint version")
            return False, [LogEvent("Invalid blueprint version", log_level="warning", logger=None)]
        with (
            transaction_rollback(),
            capture_logs() as logs,
        ):
>           successful = self._apply_models(raise_errors=raise_validation_errors)

.../blueprints/v1/importer.py:456: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7ff08f9e1be0>
raise_errors = True

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.entries:
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:397: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7ff08f9e1be0>
entry = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] BlueprintEntry object at 0x7ff08f9e0920>

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:351: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7ff08fe446e0>

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.12.............../site-packages/rest_framework/serializers.py:223: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7ff08fe446e0>
data = {'group': UUID('29bdb447-6cdf-4263-b2c6-88ad3b37cf05'), 'order': 0, 'target': UUID('130c35e2-3d9e-435a-925f-03988a19e5b0')}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.12.............../site-packages/rest_framework/serializers.py:444: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7ff08fe446e0>
value = {'group': <Group: Group VqVdbFWCJSP7RbnUEH9U7Wje1e2jR1bBux2uiUo3>, 'order': 0, 'policy': None, 'target': <Application: HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf>}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.12.............../site-packages/rest_framework/serializers.py:477: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7ff08fe446e0>
value = {'group': <Group: Group VqVdbFWCJSP7RbnUEH9U7Wje1e2jR1bBux2uiUo3>, 'order': 0, 'policy': None, 'target': <Application: HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf>}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.12.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=PolicyBinding.objects.all(), fields=('policy', 'target', 'order'))>
attrs = {'group': <Group: Group VqVdbFWCJSP7RbnUEH9U7Wje1e2jR1bBux2uiUo3>, 'order': 0, 'policy': None, 'target': <Application: HQ9yvLYf9QOt0JH07MjCbiqa9pPJe6qNfoLMwTNf>}
serializer = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7ff08fe446e0>

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [
                value for field, value in attrs.items() if field in self.fields
            ]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                value
                for field, value in attrs.items()
>               if field in self.fields and value != getattr(serializer.instance, field)
            ]

.venv/lib/python3.12.../site-packages/rest_framework/validators.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.lib.models.InheritanceForwardManyToOneDescriptor object at 0x7ff09a05ca10>
instance = <PolicyBinding: Binding - #None to Invalid invalid>
cls = <class 'authentik.policies.models.PolicyBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.policies.models.PolicyBinding.target.RelatedObjectDoesNotExist: PolicyBinding has no target.

.venv/lib/python3.12.../models/fields/related_descriptors.py:264: RelatedObjectDoesNotExist
authentik.blueprints.tests.test_packaged.TestPackaged::test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml
Stack Traces | 2.04s run time
self = <unittest.case._Outcome object at 0x7f3131a8bc50>
test_case = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>
result = <TestCaseFunction test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>
method = <bound method blueprint_tester.<locals>.tester of <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/default/flow-default-authenticator-webauthn-setup.yaml>

    def tester(self: TestPackaged):
        base = Path("blueprints/")
        rel_path = Path(file_name).relative_to(base)
        importer = Importer.from_string(BlueprintInstance(path=str(rel_path)).retrieve())
>       validation, logs = importer.validate()

.../blueprints/tests/test_packaged.py:30: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f312d19e720>
raise_validation_errors = False

    def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
        """Validate loaded blueprint export, ensure all models are allowed
        and serializers have no errors"""
        self.logger.debug("Starting blueprint import validation")
        orig_import = deepcopy(self._import)
        if self._import.version != 1:
            self.logger.warning("Invalid blueprint version")
            return False, [LogEvent("Invalid blueprint version", log_level="warning", logger=None)]
        with (
            transaction_rollback(),
            capture_logs() as logs,
        ):
>           successful = self._apply_models(raise_errors=raise_validation_errors)

.../blueprints/v1/importer.py:456: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f312d19e720>
raise_errors = False

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.entries:
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:397: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f312d19e720>
entry = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] BlueprintEntry object at 0x7f31319b9ca0>

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:351: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f31312161e0>

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:223: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f31312161e0>
data = {'order': 0, 'stage': UUID('e0c4d591-00b5-4ec3-9a64-0f6dd50e032a'), 'target': UUID('e712d252-29b5-43d5-8e88-051bd1b35cdc')}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:444: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f31312161e0>
value = {'order': 0, 'stage': <Stage: Stage default-authenticator-webauthn-setup>, 'target': <Flow: Flow default-authenticator-webauthn-setup (default-authenticator-webauthn-setup)>}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:477: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f31312161e0>
value = {'order': 0, 'stage': <Stage: Stage default-authenticator-webauthn-setup>, 'target': <Flow: Flow default-authenticator-webauthn-setup (default-authenticator-webauthn-setup)>}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.12.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>
attrs = {'order': 0, 'stage': <Stage: Stage default-authenticator-webauthn-setup>, 'target': <Flow: Flow default-authenticator-webauthn-setup (default-authenticator-webauthn-setup)>}
serializer = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-authenticator-webauthn-setup` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f31312161e0>

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [
                value for field, value in attrs.items() if field in self.fields
            ]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                value
                for field, value in attrs.items()
>               if field in self.fields and value != getattr(serializer.instance, field)
            ]

.venv/lib/python3.12.../site-packages/rest_framework/validators.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x7f313b6cf530>
instance = <FlowStageBinding: Flow-stage binding #None to None>
cls = <class 'authentik.flows.models.FlowStageBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.flows.models.FlowStageBinding.target.RelatedObjectDoesNotExist: FlowStageBinding has no target.

.venv/lib/python3.12.../models/fields/related_descriptors.py:264: RelatedObjectDoesNotExist
authentik.blueprints.tests.test_packaged.TestPackaged::test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml
Stack Traces | 2.14s run time
self = <unittest.case._Outcome object at 0x7f31311bd2b0>
test_case = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>
result = <TestCaseFunction test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>
method = <bound method blueprint_tester.<locals>.tester of <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.9........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_packaged.TestPackaged testMethod=test_blueprint_blueprints/example/flows-login-conditional-captcha.yaml>

    def tester(self: TestPackaged):
        base = Path("blueprints/")
        rel_path = Path(file_name).relative_to(base)
        importer = Importer.from_string(BlueprintInstance(path=str(rel_path)).retrieve())
>       validation, logs = importer.validate()

.../blueprints/tests/test_packaged.py:30: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f3133977920>
raise_validation_errors = False

    def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
        """Validate loaded blueprint export, ensure all models are allowed
        and serializers have no errors"""
        self.logger.debug("Starting blueprint import validation")
        orig_import = deepcopy(self._import)
        if self._import.version != 1:
            self.logger.warning("Invalid blueprint version")
            return False, [LogEvent("Invalid blueprint version", log_level="warning", logger=None)]
        with (
            transaction_rollback(),
            capture_logs() as logs,
        ):
>           successful = self._apply_models(raise_errors=raise_validation_errors)

.../blueprints/v1/importer.py:456: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f3133977920>
raise_errors = False

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.entries:
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:397: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7f3133977920>
entry = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] BlueprintEntry object at 0x7f3130fdc9e0>

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:351: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f3131216cc0>

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:223: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f3131216cc0>
data = {'order': 10, 'stage': UUID('5d56c7a6-a105-4c5c-9fa3-4f385fbc6247'), 'target': UUID('d7df70c4-0fb0-4bcc-9bee-99b4c44b73ac')}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:444: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f3131216cc0>
value = {'order': 10, 'stage': <Stage: Stage default-authentication-identification>, 'target': <Flow: Flow Default Authentication Flow (default-authentication-flow)>}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.12........./site-packages/rest_framework/serializers.py:477: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f3131216cc0>
value = {'order': 10, 'stage': <Stage: Stage default-authentication-identification>, 'target': <Flow: Flow Default Authentication Flow (default-authentication-flow)>}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.12.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>
attrs = {'order': 10, 'stage': <Stage: Stage default-authentication-identification>, 'target': <Flow: Flow Default Authentication Flow (default-authentication-flow)>}
serializer = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `flow` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7f3131216cc0>

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [
                value for field, value in attrs.items() if field in self.fields
            ]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                value
                for field, value in attrs.items()
>               if field in self.fields and value != getattr(serializer.instance, field)
            ]

.venv/lib/python3.12.../site-packages/rest_framework/validators.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x7f313b6cf530>
instance = <FlowStageBinding: Flow-stage binding #None to None>
cls = <class 'authentik.flows.models.FlowStageBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.flows.models.FlowStageBinding.target.RelatedObjectDoesNotExist: FlowStageBinding has no target.

.venv/lib/python3.12.../models/fields/related_descriptors.py:264: RelatedObjectDoesNotExist

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

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant