Files
mqtt-broker-stack/backend/pytest_output.txt
T
2026-09-16 06:08:37 +02:00

3855 lines
164 KiB
Plaintext

EEEEEEEEEEE..... [100%]
=================================== ERRORS ====================================
_____________________ ERROR at setup of test_health_live ______________________
self = <sqlalchemy.engine.base.Connection object at 0x0000019AEB75EB10>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6990>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB67BD10>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEB776D50>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6990>
cursor = <sqlite3.Cursor object at 0x0000019AEB7F77C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB67BD10>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB6EB620>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6990>
cursor = <sqlite3.Cursor object at 0x0000019AEB7F77C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB67BD10>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBAB5E50>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDC6710>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896450>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBAC9050>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDC6710>
cursor = <sqlite3.Cursor object at 0x0000019AEE5A98C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896450>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D52B0>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDC6710>
cursor = <sqlite3.Cursor object at 0x0000019AEE5A98C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896450>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEB7CE3F0>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B7250>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896210>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBACA550>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B7250>
cursor = <sqlite3.Cursor object at 0x0000019AEBC6F740>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896210>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D7E00>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B7250>
cursor = <sqlite3.Cursor object at 0x0000019AEBC6F740>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896210>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBACDB80>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6210>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB895C10>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBAC9C50>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6210>
cursor = <sqlite3.Cursor object at 0x0000019AED6F5840>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB895C10>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D5940>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6210>
cursor = <sqlite3.Cursor object at 0x0000019AED6F5840>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB895C10>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBD814F0>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6FD0>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896F90>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBDDD550>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6FD0>
cursor = <sqlite3.Cursor object at 0x0000019AEB7F7840>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896F90>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D5E80>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEB7B6FD0>
cursor = <sqlite3.Cursor object at 0x0000019AEB7F7840>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896F90>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBDD64E0>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA20D0>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897290>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBDDDF50>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA20D0>
cursor = <sqlite3.Cursor object at 0x0000019AEC086F40>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897290>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D5D30>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA20D0>
cursor = <sqlite3.Cursor object at 0x0000019AEC086F40>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897290>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBFE65D0>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA2E90>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897DD0>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBCE4850>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA2E90>
cursor = <sqlite3.Cursor object at 0x0000019AEBDB50C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897DD0>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB7D5BE0>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA2E90>
cursor = <sqlite3.Cursor object at 0x0000019AEBDB50C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB897DD0>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBDCA300>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3890>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8968D0>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBCE5F50>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3890>
cursor = <sqlite3.Cursor object at 0x0000019AEBAFA8C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8968D0>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEB6EB380>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3890>
cursor = <sqlite3.Cursor object at 0x0000019AEBAFA8C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8968D0>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBB4A120>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3C50>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896D50>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBBA0450>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3C50>
cursor = <sqlite3.Cursor object at 0x0000019AEE5AABC0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896D50>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEDC8D2B0>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3C50>
cursor = <sqlite3.Cursor object at 0x0000019AEE5AABC0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB896D50>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBB42030>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3D90>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEE96C650>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBBA2350>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3D90>
cursor = <sqlite3.Cursor object at 0x0000019AED6F4DC0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEE96C650>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEDC8D400>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBDA3D90>
cursor = <sqlite3.Cursor object at 0x0000019AED6F4DC0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEE96C650>
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 = <sqlalchemy.engine.base.Connection object at 0x0000019AEBB5EB70>
dialect = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBB80410>
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8971D0>
statement = <sqlalchemy.dialects.sqlite.base.SQLiteCompiler object at 0x0000019AEBBA2F50>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBB80410>
cursor = <sqlite3.Cursor object at 0x0000019AEE18D6C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8971D0>
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 = <sqlalchemy.orm.session.Session object at 0x0000019AEDC8DA90>
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 = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x0000019AEBB80410>
cursor = <sqlite3.Cursor object at 0x0000019AEE18D6C0>
statement = 'SELECT users.id \nFROM users \nWHERE users.role = ?'
parameters = ('SUPER_ADMIN',)
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x0000019AEB8971D0>
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