All checks passed! ============================= test session starts ============================== platform linux -- Python 3.12.13, pytest-9.1.1, pluggy-1.6.0 django: version: 6.0.6, settings: settings.test (from ini) rootdir: /app configfile: pyproject.toml testpaths: tests plugins: cov-7.1.0, django-4.12.0, asyncio-1.4.0, mock-3.15.1, anyio-4.14.0, Faker-40.23.0, factoryboy-2.8.1 asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function collected 747 items tests/assets/api/test_views.py ......... [ 1%] tests/assets/services/test_defaults.py .... [ 1%] tests/assets/test_models.py ....... [ 2%] tests/capturer/test_overlay_service.py ........ [ 3%] tests/capturer/test_tasks.py ................ [ 5%] tests/common/test_commands.py .. [ 6%] tests/compositor/api/test_views.py ..................................... [ 11%] ............. [ 12%] tests/compositor/services/test_events.py ............. [ 14%] tests/compositor/services/test_lifecycle.py ............................ [ 18%] ........................................................................ [ 27%] ................. [ 30%] tests/compositor/test_models.py .... [ 30%] tests/compositor/test_tasks.py .........FF.............................. [ 36%] .... [ 36%] tests/overlays/api/test_pack_sessions.py ......... [ 38%] tests/overlays/api/test_project_control.py .... [ 38%] tests/overlays/api/test_project_create.py ........ [ 39%] tests/overlays/api/test_project_delete.py ...... [ 40%] tests/overlays/api/test_project_list.py ........ [ 41%] tests/overlays/api/test_project_publish.py .... [ 42%] tests/overlays/api/test_project_sessions.py ............................ [ 45%] ............ [ 47%] tests/overlays/api/test_project_update.py .... [ 47%] tests/overlays/api/test_render.py ..... [ 48%] tests/overlays/api/test_views.py ............. [ 50%] tests/overlays/services/test_account_overlay_plan.py .. [ 50%] tests/overlays/services/test_control.py .................... [ 53%] tests/overlays/services/test_create_project.py ....... [ 54%] tests/overlays/services/test_defaults.py .... [ 54%] tests/overlays/services/test_delete_project.py .... [ 55%] tests/overlays/services/test_image_url_validation.py ...... [ 56%] tests/overlays/services/test_interactive.py ............................ [ 59%] ......... [ 61%] tests/overlays/services/test_packs.py ........... [ 62%] tests/overlays/services/test_resolve_render_config.py .. [ 62%] tests/overlays/services/test_seed_templates.py .......... [ 64%] tests/overlays/test_models.py ....... [ 65%] tests/recording/test_ffmpeg.py .... [ 65%] tests/recording/test_models.py ... [ 65%] tests/recording/test_tasks.py ...... [ 66%] tests/recording/test_views.py ........... [ 68%] tests/sources/api/test_views.py ...................... [ 71%] tests/sources/services/test_mediamtx.py ................................ [ 75%] .... [ 76%] tests/broadcast/test_consumers.py .... [ 76%] tests/broadcast/test_routing.py . [ 76%] tests/compositor/services/test_lifecycle.py . [ 76%] tests/overlays/test_consumers.py ........ [ 77%] tests/overlays/test_routing.py ... [ 78%] tests/overlays/test_session_consumers.py ......... [ 79%] tests/assets/test_models.py . [ 79%] tests/capturer/test_overlay_service.py ....................... [ 82%] tests/capturer/test_process_manager.py .................. [ 85%] tests/capturer/test_tasks.py ... [ 85%] tests/common/services/test_auth.py ...... [ 86%] tests/compositor/services/test_dispatcher.py ........................... [ 89%] ........................................ [ 95%] tests/compositor/test_choices.py .. [ 95%] tests/compositor/test_tasks.py .....F........ [ 97%] tests/overlays/test_choices.py ....... [ 98%] tests/overlays/test_models.py . [ 98%] tests/sources/services/test_mediamtx.py ....... [ 99%] tests/test_asgi.py . [ 99%] tests/test_storage.py ... [100%] =================================== FAILURES =================================== ______ test_notify_source_auto_removed_clears_attached_at_and_broadcasts _______ mocker = @pytest.mark.django_db def test_notify_source_auto_removed_clears_attached_at_and_broadcasts(mocker): from apps.compositor.choices import SourceType from apps.compositor.tasks import _notify_source_auto_removed from tests.compositor.factories import CompositionSourceFactory > source = CompositionSourceFactory(source_type=SourceType.IMAGE_URL, label='Canva template', stream=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/compositor/test_tasks.py:459: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/local/lib/python3.12/site-packages/factory/base.py:43: in __call__ return cls.create(**kwargs) ^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/base.py:539: in create return cls._generate(enums.CREATE_STRATEGY, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/django.py:122: in _generate return super()._generate(strategy, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/base.py:468: in _generate return step.build() ^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/builder.py:270: in build step.resolve(pre) /usr/local/lib/python3.12/site-packages/factory/builder.py:211: in resolve self.attributes[field_name] = getattr(self.stub, field_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/builder.py:356: in __getattr__ value = value.evaluate_pre( /usr/local/lib/python3.12/site-packages/factory/declarations.py:67: in evaluate_pre return self.evaluate(instance, step, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/declarations.py:228: in evaluate return deepgetattr(target, self.attribute_name, self.default) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/declarations.py:188: in deepgetattr return deepgetattr(getattr(obj, attr), subname, default) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ obj = None, name = 'id', default = def deepgetattr(obj, name, default=_UNSPECIFIED): """Try to retrieve the given attribute of an object, digging on '.'. This is an extended getattr, digging deeper if '.' is found. Args: obj (object): the object of which an attribute should be read name (str): the name of an attribute to look up. default (object): the default value to use if the attribute wasn't found Returns: the attribute pointed to by 'name', splitting on '.'. Raises: AttributeError: if obj has no 'name' attribute. """ try: if '.' in name: attr, subname = name.split('.', 1) return deepgetattr(getattr(obj, attr), subname, default) else: > return getattr(obj, name) ^^^^^^^^^^^^^^^^^^ E AttributeError: 'NoneType' object has no attribute 'id' /usr/local/lib/python3.12/site-packages/factory/declarations.py:190: AttributeError ____ test_notify_source_auto_removed_skips_already_operator_removed_source _____ mocker = @pytest.mark.django_db def test_notify_source_auto_removed_skips_already_operator_removed_source(mocker): """The operator already asked for this source's removal (removed_at set) -- don't alarm them about something they already intended.""" from django.utils import timezone from apps.compositor.choices import SourceType from apps.compositor.tasks import _notify_source_auto_removed from tests.compositor.factories import CompositionSourceFactory > source = CompositionSourceFactory(source_type=SourceType.IMAGE_URL, stream=None, removed_at=timezone.now()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/compositor/test_tasks.py:488: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/local/lib/python3.12/site-packages/factory/base.py:43: in __call__ return cls.create(**kwargs) ^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/base.py:539: in create return cls._generate(enums.CREATE_STRATEGY, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/django.py:122: in _generate return super()._generate(strategy, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/base.py:468: in _generate return step.build() ^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/builder.py:270: in build step.resolve(pre) /usr/local/lib/python3.12/site-packages/factory/builder.py:211: in resolve self.attributes[field_name] = getattr(self.stub, field_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/builder.py:356: in __getattr__ value = value.evaluate_pre( /usr/local/lib/python3.12/site-packages/factory/declarations.py:67: in evaluate_pre return self.evaluate(instance, step, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/declarations.py:228: in evaluate return deepgetattr(target, self.attribute_name, self.default) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/factory/declarations.py:188: in deepgetattr return deepgetattr(getattr(obj, attr), subname, default) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ obj = None, name = 'id', default = def deepgetattr(obj, name, default=_UNSPECIFIED): """Try to retrieve the given attribute of an object, digging on '.'. This is an extended getattr, digging deeper if '.' is found. Args: obj (object): the object of which an attribute should be read name (str): the name of an attribute to look up. default (object): the default value to use if the attribute wasn't found Returns: the attribute pointed to by 'name', splitting on '.'. Raises: AttributeError: if obj has no 'name' attribute. """ try: if '.' in name: attr, subname = name.split('.', 1) return deepgetattr(getattr(obj, attr), subname, default) else: > return getattr(obj, name) ^^^^^^^^^^^^^^^^^^ E AttributeError: 'NoneType' object has no attribute 'id' /usr/local/lib/python3.12/site-packages/factory/declarations.py:190: AttributeError _________ test_notify_source_auto_removed_no_op_for_unknown_source_id __________ mocker = def test_notify_source_auto_removed_no_op_for_unknown_source_id(mocker): from apps.compositor.tasks import _notify_source_auto_removed mock_broadcast = mocker.patch('apps.compositor.tasks.broadcast_group_event') > _notify_source_auto_removed('comp-1', '00000000-0000-0000-0000-000000000000') tests/compositor/test_tasks.py:501: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ src/apps/compositor/tasks.py:496: in _notify_source_auto_removed source = CompositionSource.objects.filter(id=sid).first() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/django/db/models/query.py:1145: in first for obj in queryset[:1]: ^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/django/db/models/query.py:390: in __iter__ self._fetch_all() /usr/local/lib/python3.12/site-packages/django/db/models/query.py:2000: in _fetch_all self._result_cache = list(self._iterable_class(self)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/django/db/models/query.py:95: in __iter__ results = compiler.execute_sql( /usr/local/lib/python3.12/site-packages/django/db/models/sql/compiler.py:1622: in execute_sql cursor = self.connection.cursor() ^^^^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/django/utils/asyncio.py:26: in inner return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py:320: in cursor return self._cursor() ^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , name = None def _cursor(self, name=None): self.close_if_health_check_failed() > self.ensure_connection() E RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it. /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py:296: RuntimeError =============================== warnings summary =============================== ../usr/local/lib/python3.12/site-packages/channels/http.py:1 /usr/local/lib/python3.12/site-packages/channels/http.py:1: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13 import cgi ../usr/local/lib/python3.12/site-packages/lark/utils.py:150 /usr/local/lib/python3.12/site-packages/lark/utils.py:150: DeprecationWarning: module 'sre_parse' is deprecated import sre_parse ../usr/local/lib/python3.12/site-packages/lark/utils.py:151 /usr/local/lib/python3.12/site-packages/lark/utils.py:151: DeprecationWarning: module 'sre_constants' is deprecated import sre_constants tests/test_storage.py::test_storage_env_keys_defined /app:0: PytestWarning: Error when trying to teardown test databases: OperationalError('database "test_sink" is being accessed by other users\nDETAIL: There is 1 other session using the database.\n') -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ FAILED tests/compositor/test_tasks.py::test_notify_source_auto_removed_clears_attached_at_and_broadcasts FAILED tests/compositor/test_tasks.py::test_notify_source_auto_removed_skips_already_operator_removed_source FAILED tests/compositor/test_tasks.py::test_notify_source_auto_removed_no_op_for_unknown_source_id ================== 3 failed, 744 passed, 4 warnings in 35.91s ==================