EEEEEEEEEEE..... [100%] =================================== ERRORS ==================================== _____________________ ERROR at setup of test_health_live ______________________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEB75DCD0> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ____________ ERROR at setup of test_login_sets_cookie_and_session _____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEB75F490> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError _____________ ERROR at setup of test_login_wrong_password_audited _____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEB73E450> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError _____________ ERROR at setup of test_unauthenticated_api_rejected _____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBA88160> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ____________ ERROR at setup of test_auditor_cannot_create_clients _____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBA8A8B0> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError _________ ERROR at setup of test_create_client_returns_password_once __________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBDDDE50> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError _____________ ERROR at setup of test_disable_enable_delete_client _____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBDDFE50> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError __________________ ERROR at setup of test_role_acl_lifecycle __________________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBDC8F50> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ___________________ ERROR at setup of test_group_lifecycle ____________________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBB48C80> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ___________ ERROR at setup of test_listener_management_and_preview ____________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBDCE6D0> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ________________ ERROR at setup of test_audit_events_recorded _________________ self = dialect = context = statement = parameters = [('SUPER_ADMIN',)] def _exec_single_context( self, dialect: Dialect, context: ExecutionContext, statement: Union[str, Compiled], parameters: Optional[_AnyMultiExecuteParams], ) -> CursorResult[Any]: """continue the _execute_context() method for a single DBAPI cursor.execute() or cursor.executemany() call. """ if dialect.bind_typing is BindTyping.SETINPUTSIZES: generic_setinputsizes = context._prepare_set_input_sizes() if generic_setinputsizes: try: dialect.do_set_input_sizes( context.cursor, generic_setinputsizes, context ) except BaseException as e: self._handle_dbapi_exception( e, str(statement), parameters, None, context ) cursor, str_statement, parameters = ( context.cursor, context.statement, context.parameters, ) effective_parameters: Optional[_AnyExecuteParams] if not context.executemany: effective_parameters = parameters[0] else: effective_parameters = parameters if self._has_events or self.engine._has_events: for fn in self.dispatch.before_cursor_execute: str_statement, effective_parameters = fn( self, cursor, str_statement, effective_parameters, context, context.executemany, ) if self._echo: self._log_info(str_statement) stats = context._get_cache_stats() if not self.engine.hide_parameters: self._log_info( "[%s] %r", stats, sql_util._repr_params( effective_parameters, batches=10, ismulti=context.executemany, ), ) else: self._log_info( "[%s] [SQL parameters hidden due to hide_parameters=True]", stats, ) evt_handled: bool = False try: if context.execute_style is ExecuteStyle.EXECUTEMANY: effective_parameters = cast( "_CoreMultiExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_executemany: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: self.dialect.do_executemany( cursor, str_statement, effective_parameters, context, ) elif not effective_parameters and context.no_parameters: if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute_no_params: if fn(cursor, str_statement, context): evt_handled = True break if not evt_handled: self.dialect.do_execute_no_params( cursor, str_statement, context ) else: effective_parameters = cast( "_CoreSingleExecuteParams", effective_parameters ) if self.dialect._has_events: for fn in self.dialect.dispatch.do_execute: if fn( cursor, str_statement, effective_parameters, context, ): evt_handled = True break if not evt_handled: > self.dialect.do_execute( cursor, str_statement, effective_parameters, context ) .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlite3.OperationalError: no such table: users .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError The above exception was the direct cause of the following exception: db_session = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000019AEBBC2DD0> @pytest.fixture() def client(db_session, monkeypatch): """TestClient wired to the fixture DB; dynsec calls are faked out.""" # Point the app's session factory at the test engine. monkeypatch.setattr(db_module, "_SessionFactory", None) monkeypatch.setattr( db_module, "_engine", db_session.get_bind() ) # Fake dynsec so no broker is needed for API tests. class FakeDynsec: def __init__(self): self.clients: dict[str, dict] = {} self.roles: dict[str, dict] = {} self.groups: dict[str, dict] = {} def _command(self, command, **kwargs): return {"success": True} def create_client(self, username, password, **kwargs): self.clients[username] = {"username": username, "enabled": True, **kwargs} def list_clients(self): return list(self.clients.values()) def delete_client(self, username): self.clients.pop(username, None) def disable_client(self, username): self.clients[username]["enabled"] = False def enable_client(self, username): self.clients[username]["enabled"] = True def set_client_password(self, username, password): pass def get_client(self, username): return self.clients[username] def create_group(self, groupname, roles=None): self.groups[groupname] = {"groupname": groupname, "roles": roles or []} def list_groups(self): return list(self.groups.values()) def delete_group(self, groupname): self.groups.pop(groupname, None) def create_role(self, rolename, acls=None): self.roles[rolename] = {"rolename": rolename, "acls": acls or []} def list_roles(self): return list(self.roles.values()) def delete_role(self, rolename): self.roles.pop(rolename, None) def set_role_acls(self, rolename, acls): self.roles[rolename]["acls"] = acls def get_role(self, rolename): return self.roles[rolename] def connect(self): pass def close(self): pass fake = FakeDynsec() monkeypatch.setattr(main_module, "dynsec_client", fake) from app.routers import mqtt as mqtt_router monkeypatch.setattr(mqtt_router, "dynsec_client", fake) > with TestClient(main_module.app) as test_client: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests\conftest.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ .venv\Lib\site-packages\starlette\testclient.py:698: in __enter__ portal.call(self.wait_startup) .venv\Lib\site-packages\anyio\from_thread.py:340: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:450: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:733: in wait_startup await receive() .venv\Lib\site-packages\starlette\testclient.py:724: in receive self.task.result() ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:443: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\concurrent\futures\_base.py:395: in __get_result raise self._exception .venv\Lib\site-packages\anyio\from_thread.py:265: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\starlette\testclient.py:714: in lifespan await self.app(scope, self.stream_receive.receive, self.stream_send.send) .venv\Lib\site-packages\fastapi\applications.py:1163: in __call__ await super().__call__(scope, receive, send) .venv\Lib\site-packages\starlette\applications.py:96: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\errors.py:151: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\base.py:103: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\cors.py:80: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\middleware\exceptions.py:49: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\fastapi\middleware\asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:670: in __call__ await self.middleware_stack(scope, receive, send) .venv\Lib\site-packages\fastapi\routing.py:2726: in app await self.lifespan(scope, receive, send) .venv\Lib\site-packages\starlette\routing.py:648: in lifespan async with self.lifespan_context(app) as maybe_state: ^^^^^^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ .venv\Lib\site-packages\fastapi\routing.py:240: in merged_lifespan async with original_context(app) as maybe_original_state: ^^^^^^^^^^^^^^^^^^^^^ ..\..\..\..\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:214: in __aenter__ return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ app\main.py:65: in lifespan _bootstrap_admin() app\main.py:34: in _bootstrap_admin has_admin = session.scalar( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2421: in scalar return self._execute_internal( .venv\Lib\site-packages\sqlalchemy\orm\session.py:2271: in _execute_internal result: Result[Any] = compile_state_cls.orm_execute_statement( .venv\Lib\site-packages\sqlalchemy\orm\context.py:306: in orm_execute_statement result = conn.execute( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1421: in execute return meth( .venv\Lib\site-packages\sqlalchemy\sql\elements.py:526: in _execute_on_connection return connection._execute_clauseelement( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1643: in _execute_clauseelement ret = self._execute_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1848: in _execute_context return self._exec_single_context( .venv\Lib\site-packages\sqlalchemy\engine\base.py:1988: in _exec_single_context self._handle_dbapi_exception( .venv\Lib\site-packages\sqlalchemy\engine\base.py:2365: in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e .venv\Lib\site-packages\sqlalchemy\engine\base.py:1969: in _exec_single_context self.dialect.do_execute( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = cursor = statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?' parameters = ('SUPER_ADMIN',) context = def do_execute(self, cursor, statement, parameters, context=None): > cursor.execute(statement, parameters) E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users E [SQL: SELECT users.id E FROM users E WHERE users.role = ?] E [parameters: ('SUPER_ADMIN',)] E (Background on this error at: https://sqlalche.me/e/20/e3q8) .venv\Lib\site-packages\sqlalchemy\engine\default.py:952: OperationalError ============================== warnings summary =============================== .venv\Lib\site-packages\fastapi\testclient.py:1 C:\Users\jonas\Documents\Git\mqtt-broker-stack\backend\.venv\Lib\site-packages\fastapi\testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. from starlette.testclient import TestClient as TestClient # noqa .venv\Lib\site-packages\starlette\testclient.py:53 C:\Users\jonas\Documents\Git\mqtt-broker-stack\backend\.venv\Lib\site-packages\starlette\testclient.py:53: DeprecationWarning: The anyio.abc.BlockingPortal alias is deprecated, use anyio.from_thread.BlockingPortal instead. _PortalFactoryType = Callable[[], AbstractContextManager[anyio.abc.BlockingPortal]] -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info =========================== ERROR tests/test_api.py::test_health_live - sqlalchemy.exc.OperationalError: ... ERROR tests/test_api.py::test_login_sets_cookie_and_session - sqlalchemy.exc.... ERROR tests/test_api.py::test_login_wrong_password_audited - sqlalchemy.exc.O... ERROR tests/test_api.py::test_unauthenticated_api_rejected - sqlalchemy.exc.O... ERROR tests/test_api.py::test_auditor_cannot_create_clients - sqlalchemy.exc.... ERROR tests/test_api.py::test_create_client_returns_password_once - sqlalchem... ERROR tests/test_api.py::test_disable_enable_delete_client - sqlalchemy.exc.O... ERROR tests/test_api.py::test_role_acl_lifecycle - sqlalchemy.exc.Operational... ERROR tests/test_api.py::test_group_lifecycle - sqlalchemy.exc.OperationalErr... ERROR tests/test_api.py::test_listener_management_and_preview - sqlalchemy.ex... ERROR tests/test_api.py::test_audit_events_recorded - sqlalchemy.exc.Operatio... 5 passed, 2 warnings, 11 errors in 11.71s