openmodule 14.3.0__tar.gz → 15.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openmodule-14.3.0/openmodule.egg-info → openmodule-15.0.0}/PKG-INFO +29 -8
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/alert.py +8 -8
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/config.py +5 -5
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/connection_status.py +8 -9
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/core.py +4 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/database/custom_types.py +6 -9
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/database/env.py +2 -2
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/database/migration.py +11 -10
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/dispatcher.py +27 -24
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/health.py +65 -66
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/messaging.py +1 -2
- openmodule-15.0.0/openmodule/models/access_service.py +93 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/alert.py +10 -10
- openmodule-15.0.0/openmodule/models/base.py +194 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/io.py +6 -10
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/kv_store.py +8 -10
- openmodule-15.0.0/openmodule/models/presence.py +85 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/privacy.py +12 -13
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/rpc.py +10 -10
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/settings.py +7 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/signals.py +8 -9
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/validation.py +10 -13
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/models/vehicle.py +22 -24
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/rpc/client.py +17 -10
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/rpc/server.py +10 -13
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/sentry.py +21 -23
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/access_service.py +8 -9
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/charset.py +9 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/cleanup.py +3 -4
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/csv_export.py +19 -20
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/eventlog.py +44 -40
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/io.py +20 -19
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/kv_store.py +18 -19
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/matching.py +1 -2
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/misc_functions.py +5 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/package_reader.py +24 -26
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/presence.py +25 -25
- openmodule-15.0.0/openmodule/utils/schedule.py +937 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/schema.py +1 -1
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/settings.py +9 -8
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/signal_listener.py +15 -15
- {openmodule-14.3.0 → openmodule-15.0.0/openmodule.egg-info}/PKG-INFO +29 -8
- openmodule-15.0.0/openmodule.egg-info/SOURCES.txt +101 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule.egg-info/requires.txt +6 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/setup.cfg +0 -2
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_alembic_migrations.py +2 -1
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_checks.py +4 -11
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_config.py +3 -3
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_connection_status.py +13 -12
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_database.py +7 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_health.py +22 -22
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_io_listen.py +5 -5
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_model.py +13 -13
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_rpc.py +19 -17
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_sentry.py +21 -21
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_test_gate.py +2 -2
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_test_zeromq.py +1 -1
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_access_service.py +35 -25
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_cleanup.py +6 -5
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_csv_export.py +3 -4
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_eventlog.py +6 -4
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_kv_store.py +3 -4
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_kv_store_multiple.py +14 -12
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_presence.py +134 -45
- openmodule-15.0.0/tests/test_utils_schedule.py +1622 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_settings.py +22 -10
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_signal.py +17 -7
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_validation.py +8 -5
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_vehicle.py +3 -3
- openmodule-14.3.0/.gitlab-ci.yml +0 -108
- openmodule-14.3.0/AUTHORS +0 -11
- openmodule-14.3.0/ChangeLog +0 -207
- openmodule-14.3.0/docs/access_service.md +0 -322
- openmodule-14.3.0/docs/anonymization.md +0 -52
- openmodule-14.3.0/docs/cleanup.md +0 -42
- openmodule-14.3.0/docs/coding_standard.md +0 -79
- openmodule-14.3.0/docs/commands.md +0 -20
- openmodule-14.3.0/docs/connection_status_listener.md +0 -67
- openmodule-14.3.0/docs/csv_export.md +0 -160
- openmodule-14.3.0/docs/database.md +0 -248
- openmodule-14.3.0/docs/deprecated.md +0 -56
- openmodule-14.3.0/docs/deprecated_code/README.md +0 -5
- openmodule-14.3.0/docs/deprecated_code/access_service/openmodule/models/access_service.py +0 -279
- openmodule-14.3.0/docs/deprecated_code/access_service/openmodule/utils/access_service.py +0 -352
- openmodule-14.3.0/docs/deprecated_code/access_service/openmodule_test/access_service.py +0 -154
- openmodule-14.3.0/docs/deprecated_code/access_service/tests/test_utils_access_service.py +0 -487
- openmodule-14.3.0/docs/deprecated_code/api/openmodule/utils/api.py +0 -93
- openmodule-14.3.0/docs/deprecated_code/api/openmodule_test/api.py +0 -58
- openmodule-14.3.0/docs/deprecated_code/api/tests/test_utils_api.py +0 -97
- openmodule-14.3.0/docs/deprecated_code/package_reader/openmodule/utils/package_reader.py +0 -190
- openmodule-14.3.0/docs/deprecated_code/package_reader/openmodule_test/fake_package_creator.py +0 -94
- openmodule-14.3.0/docs/deprecated_code/package_reader/tests/test_package_reader.py +0 -145
- openmodule-14.3.0/docs/event_sending.md +0 -73
- openmodule-14.3.0/docs/getting_started.md +0 -323
- openmodule-14.3.0/docs/health.md +0 -261
- openmodule-14.3.0/docs/images/broker.drawio.png +0 -0
- openmodule-14.3.0/docs/known_issues.md +0 -191
- openmodule-14.3.0/docs/migrations.md +0 -231
- openmodule-14.3.0/docs/package_reader.md +0 -65
- openmodule-14.3.0/docs/rpc.md +0 -171
- openmodule-14.3.0/docs/sentry.md +0 -99
- openmodule-14.3.0/docs/settings.md +0 -60
- openmodule-14.3.0/docs/settings_provider.md +0 -77
- openmodule-14.3.0/docs/testing.md +0 -515
- openmodule-14.3.0/docs/translation.md +0 -156
- openmodule-14.3.0/docs/utils.md +0 -87
- openmodule-14.3.0/openmodule/models/access_service.py +0 -98
- openmodule-14.3.0/openmodule/models/base.py +0 -176
- openmodule-14.3.0/openmodule/models/presence.py +0 -95
- openmodule-14.3.0/openmodule.egg-info/SOURCES.txt +0 -251
- openmodule-14.3.0/openmodule.egg-info/pbr.json +0 -1
- openmodule-14.3.0/openmodule_commands/__init__.py +0 -51
- openmodule-14.3.0/openmodule_commands/setup.cfg +0 -23
- openmodule-14.3.0/openmodule_commands/setup.py +0 -16
- openmodule-14.3.0/openmodule_commands/translate.py +0 -206
- openmodule-14.3.0/openmodule_test/alert.py +0 -14
- openmodule-14.3.0/openmodule_test/connection_status.py +0 -40
- openmodule-14.3.0/openmodule_test/core.py +0 -29
- openmodule-14.3.0/openmodule_test/database.py +0 -152
- openmodule-14.3.0/openmodule_test/eventlistener.py +0 -73
- openmodule-14.3.0/openmodule_test/files.py +0 -14
- openmodule-14.3.0/openmodule_test/gate.py +0 -86
- openmodule-14.3.0/openmodule_test/health.py +0 -46
- openmodule-14.3.0/openmodule_test/interrupt.py +0 -197
- openmodule-14.3.0/openmodule_test/io_simulator.py +0 -98
- openmodule-14.3.0/openmodule_test/package_reader.py +0 -150
- openmodule-14.3.0/openmodule_test/presence.py +0 -187
- openmodule-14.3.0/openmodule_test/requirements.txt +0 -2
- openmodule-14.3.0/openmodule_test/rpc.py +0 -119
- openmodule-14.3.0/openmodule_test/sentry.py +0 -67
- openmodule-14.3.0/openmodule_test/settings.py +0 -118
- openmodule-14.3.0/openmodule_test/setup.cfg +0 -17
- openmodule-14.3.0/openmodule_test/setup.py +0 -16
- openmodule-14.3.0/openmodule_test/signal_simulator.py +0 -58
- openmodule-14.3.0/openmodule_test/utils.py +0 -36
- openmodule-14.3.0/openmodule_test/zeromq.py +0 -520
- openmodule-14.3.0/requirements.txt +0 -13
- openmodule-14.3.0/test-requirements.txt +0 -5
- openmodule-14.3.0/tests/__init__.py +0 -0
- openmodule-14.3.0/tests/config.py +0 -13
- openmodule-14.3.0/tests/database_models_migration.py +0 -23
- openmodule-14.3.0/tests/database_models_test.py +0 -24
- openmodule-14.3.0/tests/invalid_database/alembic/README +0 -1
- openmodule-14.3.0/tests/invalid_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/invalid_database/alembic/env.py +0 -15
- openmodule-14.3.0/tests/invalid_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/invalid_database/alembic/versions/ff26e54332f9_datetime_models.py +0 -32
- openmodule-14.3.0/tests/invalid_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/invalid_database/makemigration.sh +0 -21
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic/env.py +0 -4
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic/versions/812a3e5b8517_initial.py +0 -62
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic/versions/a7ea100a784f_key_error.py +0 -40
- openmodule-14.3.0/tests/migration_double_column_delete_error/alembic.ini +0 -85
- openmodule-14.3.0/tests/migration_double_column_delete_error/makemigration.sh +0 -21
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic/env.py +0 -4
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic/versions/812a3e5b8517_initial.py +0 -62
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic/versions/a7ea100a784f_no_such_table_error.py +0 -39
- openmodule-14.3.0/tests/migration_no_such_table_error/alembic.ini +0 -85
- openmodule-14.3.0/tests/migration_no_such_table_error/makemigration.sh +0 -21
- openmodule-14.3.0/tests/migration_test_database/__init__.py +0 -0
- openmodule-14.3.0/tests/migration_test_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/migration_test_database/alembic/env.py +0 -4
- openmodule-14.3.0/tests/migration_test_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/migration_test_database/alembic/versions/19789aa5361c_initial.py +0 -40
- openmodule-14.3.0/tests/migration_test_database/alembic/versions/19d887929ae7_alter.py +0 -40
- openmodule-14.3.0/tests/migration_test_database/alembic/versions/__init__.py +0 -0
- openmodule-14.3.0/tests/migration_test_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/migration_test_database/alembic_migration_test_database.sqlite3 +0 -0
- openmodule-14.3.0/tests/migration_test_database/makemigration.sh +0 -21
- openmodule-14.3.0/tests/resources/configs/config.py +0 -9
- openmodule-14.3.0/tests/resources/configs/test_config.py +0 -9
- openmodule-14.3.0/tests/resources/configs/test_config_1.py +0 -5
- openmodule-14.3.0/tests/resources/standard_schemes/DEFAULT-10.yml +0 -10
- openmodule-14.3.0/tests/resources/standard_schemes/DEFAULT-20.yml +0 -10
- openmodule-14.3.0/tests/resources/standard_schemes/LEGACY-0.yml +0 -14
- openmodule-14.3.0/tests/resources/translation/locale/de/LC_MESSAGES/translation.mo +0 -0
- openmodule-14.3.0/tests/resources/translation/locale/de/LC_MESSAGES/translation.po +0 -21
- openmodule-14.3.0/tests/resources/translation/locale/en/LC_MESSAGES/translation.mo +0 -0
- openmodule-14.3.0/tests/resources/translation/locale/en/LC_MESSAGES/translation.po +0 -21
- openmodule-14.3.0/tests/resources/translation/locale/translation.pot +0 -8
- openmodule-14.3.0/tests/resources/translation/translate.sh +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/A-10.yml +0 -18
- openmodule-14.3.0/tests/resources/utils_matching/A-20.yml +0 -12
- openmodule-14.3.0/tests/resources/utils_matching/DEFAULT-10.yml +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/DEFAULT-20.yml +0 -10
- openmodule-14.3.0/tests/resources/utils_matching/DEFAULT-30.yml +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/LEGACY-0.yml +0 -14
- openmodule-14.3.0/tests/resources/utils_matching/TEST-10.yml +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/TEST-20.yml +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/TEST-30.yml +0 -3
- openmodule-14.3.0/tests/resources/utils_matching/TEST-40.yml +0 -3
- openmodule-14.3.0/tests/sentry_main.py +0 -32
- openmodule-14.3.0/tests/test_access_service_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/test_access_service_database/alembic/env.py +0 -4
- openmodule-14.3.0/tests/test_access_service_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/test_access_service_database/alembic/versions/7bd4fcd38fde_removed_nfc_and_pin.py +0 -42
- openmodule-14.3.0/tests/test_access_service_database/alembic/versions/9ca98a2e5674_added_parksettings_id.py +0 -36
- openmodule-14.3.0/tests/test_access_service_database/alembic/versions/c821971f9230_initial.py +0 -67
- openmodule-14.3.0/tests/test_access_service_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/test_access_service_database/makemigration.sh +0 -21
- openmodule-14.3.0/tests/test_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/test_database/alembic/env.py +0 -4
- openmodule-14.3.0/tests/test_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/test_database/alembic/versions/32b8c728abbf_initial.py +0 -43
- openmodule-14.3.0/tests/test_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/test_database/makemigration.sh +0 -21
- openmodule-14.3.0/tests/test_kv_store_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/test_kv_store_database/alembic/env.py +0 -4
- openmodule-14.3.0/tests/test_kv_store_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/test_kv_store_database/alembic/versions/9c5c944221f4_deprecated_kv_entry_example.py +0 -45
- openmodule-14.3.0/tests/test_kv_store_database/alembic/versions/c55a69026a25_initial.py +0 -46
- openmodule-14.3.0/tests/test_kv_store_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/test_kv_store_database/makemigration.sh +0 -21
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic/README +0 -1
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic/__init__.py +0 -0
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic/env.py +0 -4
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic/script.py.mako +0 -24
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic/versions/cdb3214131a9_initial.py +0 -87
- openmodule-14.3.0/tests/test_kv_store_multiple_database/alembic.ini +0 -85
- openmodule-14.3.0/tests/test_kv_store_multiple_database/makemigration.sh +0 -21
- openmodule-14.3.0/tox.ini +0 -31
- {openmodule-14.3.0 → openmodule-15.0.0}/LICENSE +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/README.md +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/__init__.py +0 -0
- {openmodule-14.3.0/openmodule/models → openmodule-15.0.0/openmodule/database}/__init__.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/database/database.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/logging.py +0 -0
- {openmodule-14.3.0/openmodule/utils → openmodule-15.0.0/openmodule/models}/__init__.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/rpc/__init__.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/rpc/common.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/threading.py +0 -0
- {openmodule-14.3.0/openmodule_test → openmodule-15.0.0/openmodule/utils}/__init__.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/databox.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/db_helper.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/translation.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule/utils/validation.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule.egg-info/dependency_links.txt +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule.egg-info/not-zip-safe +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/openmodule.egg-info/top_level.txt +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/setup.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_alert.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_core.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_dispatcher.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_interrupt.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_logging.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_messaging.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_mockrpcclient.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_schema.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_test_alert.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_charset.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_databox.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_matching.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_misc_functions.py +0 -0
- {openmodule-14.3.0 → openmodule-15.0.0}/tests/test_utils_package_reader.py +0 -0
|
@@ -1,23 +1,46 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: openmodule
|
|
3
|
-
Version:
|
|
3
|
+
Version: 15.0.0
|
|
4
4
|
Summary: Libraries for developing the arivo openmodule
|
|
5
5
|
Home-page: https://gitlab.com/arivo-public/device-python/openmodule.git
|
|
6
6
|
Author: ARIVO
|
|
7
7
|
Author-email: support@arivo.co
|
|
8
8
|
License: GNU General Public License v2 (GPLv2)
|
|
9
9
|
Keywords: arivo openmodule
|
|
10
|
-
Platform: UNKNOWN
|
|
11
10
|
Classifier: Intended Audience :: Developers
|
|
12
11
|
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
|
|
13
12
|
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
14
|
Description-Content-Type: text/markdown; charset=UTF-8
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: pydantic~=2.0
|
|
17
|
+
Requires-Dist: sentry-sdk~=2.19.0
|
|
18
|
+
Requires-Dist: orjson<4,>=3.4.7
|
|
19
|
+
Requires-Dist: pyzmq~=26.2
|
|
20
|
+
Requires-Dist: pyyaml<7,>=5.0
|
|
21
|
+
Requires-Dist: editdistance>=0.8.1
|
|
22
|
+
Requires-Dist: sqlalchemy~=2.0.0
|
|
23
|
+
Requires-Dist: alembic<2,>=1.5.4
|
|
24
|
+
Requires-Dist: requests<3,>=2.22
|
|
25
|
+
Requires-Dist: python-dateutil>=2.7.2
|
|
26
|
+
Requires-Dist: python-dotenv~=0.15
|
|
27
|
+
Requires-Dist: arivo-settings_models~=2.2
|
|
18
28
|
Provides-Extra: test
|
|
29
|
+
Requires-Dist: openmodule_test; extra == "test"
|
|
19
30
|
Provides-Extra: commands
|
|
20
|
-
|
|
31
|
+
Requires-Dist: openmodule_commands; extra == "commands"
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: author-email
|
|
34
|
+
Dynamic: classifier
|
|
35
|
+
Dynamic: description
|
|
36
|
+
Dynamic: description-content-type
|
|
37
|
+
Dynamic: home-page
|
|
38
|
+
Dynamic: keywords
|
|
39
|
+
Dynamic: license
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
Dynamic: provides-extra
|
|
42
|
+
Dynamic: requires-dist
|
|
43
|
+
Dynamic: summary
|
|
21
44
|
|
|
22
45
|
# OpenModule V2
|
|
23
46
|
|
|
@@ -130,5 +153,3 @@ pip install -e <path_to_openmodule_root>/openmodule_commands/
|
|
|
130
153
|
|
|
131
154
|
- [Openmodule Commands](docs/commands.md)
|
|
132
155
|
|
|
133
|
-
|
|
134
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import threading
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from openmodule.models.alert import AlertHandleType, AlertMessage, AlertStatus
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class AlertHandler(object):
|
|
12
|
-
_alerts:
|
|
12
|
+
_alerts: list[dict]
|
|
13
13
|
|
|
14
14
|
def __init__(self, core: 'OpenModuleCore'):
|
|
15
15
|
self._alerts = []
|
|
@@ -42,8 +42,8 @@ class AlertHandler(object):
|
|
|
42
42
|
return False
|
|
43
43
|
|
|
44
44
|
def get_or_add_alert_id(self, alert_type: str, handle_type: AlertHandleType, *,
|
|
45
|
-
package_name:
|
|
46
|
-
always_send_alert:
|
|
45
|
+
package_name: str | None = None, version: str | None = None,
|
|
46
|
+
always_send_alert: bool | None = None, source: str = ""):
|
|
47
47
|
"""Define an alert with its name parameters
|
|
48
48
|
|
|
49
49
|
Args:
|
|
@@ -78,7 +78,7 @@ class AlertHandler(object):
|
|
|
78
78
|
self._alerts.append(alert)
|
|
79
79
|
return alert["id"]
|
|
80
80
|
|
|
81
|
-
def send_with_alert_id(self, alert_id: int, status: AlertStatus, meta:
|
|
81
|
+
def send_with_alert_id(self, alert_id: int, status: AlertStatus, meta: dict, value: float | None = None):
|
|
82
82
|
""" Send a status message on the given alert with the corresponding meta/kwarg arguments
|
|
83
83
|
Returns True if alert was send else False"""
|
|
84
84
|
assert status in [AlertStatus.error, AlertStatus.ok, AlertStatus.offline]
|
|
@@ -93,9 +93,9 @@ class AlertHandler(object):
|
|
|
93
93
|
return self._send_message(alert_id, status_dict)
|
|
94
94
|
|
|
95
95
|
def send(self, alert_type: str, handle_type: AlertHandleType, *,
|
|
96
|
-
package_name:
|
|
97
|
-
always_send_alert:
|
|
98
|
-
meta:
|
|
96
|
+
package_name: str | None = None, version: str | None = None,
|
|
97
|
+
always_send_alert: bool | None = None, status: AlertStatus = AlertStatus.error,
|
|
98
|
+
meta: dict | None = None, value: float | None = None, source: str = ""):
|
|
99
99
|
|
|
100
100
|
"""Sends an alert to the device serve
|
|
101
101
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import builtins
|
|
2
2
|
import functools
|
|
3
3
|
import glob
|
|
4
|
-
import importlib
|
|
4
|
+
import importlib
|
|
5
5
|
import inspect
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
8
|
import warnings
|
|
9
9
|
from contextlib import contextmanager
|
|
10
10
|
from socket import gethostname
|
|
11
|
-
from typing import
|
|
11
|
+
from typing import TypeVar
|
|
12
12
|
|
|
13
13
|
import yaml
|
|
14
14
|
from pydantic import ValidationError
|
|
@@ -49,7 +49,7 @@ def bool(key: str, default: bool = False) -> bool:
|
|
|
49
49
|
return val in ["T", "TRUE", "1", "Y", "YES", "J", "JA", "ON"]
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def get(key: str, default:
|
|
52
|
+
def get(key: str, default: str | None = "") -> str:
|
|
53
53
|
return os.environ.get(key, default)
|
|
54
54
|
|
|
55
55
|
|
|
@@ -213,7 +213,7 @@ def config_yaml_path():
|
|
|
213
213
|
return yaml_path
|
|
214
214
|
|
|
215
215
|
|
|
216
|
-
def yaml(model:
|
|
216
|
+
def yaml(model: type[YamlType], path: str | None = None) -> YamlType:
|
|
217
217
|
yaml_path = path or config_yaml_path()
|
|
218
218
|
|
|
219
219
|
try:
|
|
@@ -221,7 +221,7 @@ def yaml(model: Type[YamlType], path: str = None) -> YamlType:
|
|
|
221
221
|
import yaml
|
|
222
222
|
with open(yaml_path, "r") as f:
|
|
223
223
|
a = yaml.load(f, SafeLoaderIgnoreUnknown)
|
|
224
|
-
return model.
|
|
224
|
+
return model.model_validate(a or {})
|
|
225
225
|
else:
|
|
226
226
|
return model()
|
|
227
227
|
except ValidationError as e:
|
|
@@ -1,41 +1,40 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import threading
|
|
3
3
|
import time
|
|
4
|
-
from enum import
|
|
5
|
-
from typing import Optional, Set
|
|
4
|
+
from enum import StrEnum
|
|
6
5
|
|
|
7
6
|
from openmodule import sentry
|
|
8
7
|
from openmodule.dispatcher import MessageDispatcher
|
|
9
8
|
from openmodule.models.base import ZMQMessage, OpenModuleModel
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
class ConnectionStatus(
|
|
11
|
+
class ConnectionStatus(StrEnum):
|
|
13
12
|
startup = "startup"
|
|
14
13
|
online = "online"
|
|
15
14
|
shutdown = "shutdown"
|
|
16
15
|
offline = "offline"
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class BridgeStatus(
|
|
18
|
+
class BridgeStatus(StrEnum):
|
|
20
19
|
online = "online"
|
|
21
20
|
offline = "offline"
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class ConnectionStatusMessage(ZMQMessage):
|
|
25
24
|
connected: ConnectionStatus
|
|
26
|
-
bridge_status:
|
|
25
|
+
bridge_status: BridgeStatus | None = None
|
|
27
26
|
type: str = "connection_status"
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
class ConnectionRPCResponse(OpenModuleModel):
|
|
31
30
|
connected: ConnectionStatus
|
|
32
|
-
bridge_status:
|
|
31
|
+
bridge_status: BridgeStatus | None = None
|
|
33
32
|
|
|
34
33
|
|
|
35
34
|
class ConnectionStatusListener:
|
|
36
35
|
def __init__(self, dispatcher: MessageDispatcher, rpc_client):
|
|
37
36
|
self._log = logging.getLogger(self.__class__.__name__)
|
|
38
|
-
self._status:
|
|
37
|
+
self._status: ConnectionRPCResponse | None = None
|
|
39
38
|
self._previous_status: ConnectionRPCResponse = ConnectionRPCResponse(connected=ConnectionStatus.shutdown)
|
|
40
39
|
self._changed = threading.Condition(threading.Lock())
|
|
41
40
|
self.last_changed_time = 0.0
|
|
@@ -44,7 +43,7 @@ class ConnectionStatusListener:
|
|
|
44
43
|
self.rpc_client = rpc_client
|
|
45
44
|
self._listener = dispatcher.register_handler("connection_internal", ConnectionStatusMessage,
|
|
46
45
|
self._process_connection_status)
|
|
47
|
-
self._got_change_ids:
|
|
46
|
+
self._got_change_ids: set[str] = set()
|
|
48
47
|
self._got_change_ids_lock = threading.Lock()
|
|
49
48
|
|
|
50
49
|
def wait_for_change(self, timeout: float = None) -> bool:
|
|
@@ -115,7 +114,7 @@ class ConnectionStatusListener:
|
|
|
115
114
|
self._status = ConnectionRPCResponse(connected=ConnectionStatus.shutdown)
|
|
116
115
|
return self._status
|
|
117
116
|
|
|
118
|
-
def _set(self, status: ConnectionStatus, bridge_status:
|
|
117
|
+
def _set(self, status: ConnectionStatus, bridge_status: BridgeStatus | None = None):
|
|
119
118
|
if not self._status or status != self._status.connected or \
|
|
120
119
|
(bridge_status and bridge_status != self._status.bridge_status):
|
|
121
120
|
self._previous_status = self._status or self._previous_status # initial status is None
|
|
@@ -7,7 +7,6 @@ import warnings
|
|
|
7
7
|
from concurrent.futures.thread import ThreadPoolExecutor
|
|
8
8
|
|
|
9
9
|
import zmq
|
|
10
|
-
from typing import Optional
|
|
11
10
|
|
|
12
11
|
from openmodule import sentry
|
|
13
12
|
from openmodule.alert import AlertHandler
|
|
@@ -65,7 +64,7 @@ class OpenModuleCore(threading.Thread):
|
|
|
65
64
|
super().start()
|
|
66
65
|
self.internal_thread.start()
|
|
67
66
|
|
|
68
|
-
def join(self, timeout:
|
|
67
|
+
def join(self, timeout: float | None = None) -> None:
|
|
69
68
|
super().join(timeout)
|
|
70
69
|
self.internal_thread.join(timeout)
|
|
71
70
|
|
|
@@ -97,7 +96,6 @@ class OpenModuleCore(threading.Thread):
|
|
|
97
96
|
@sentry.trace(op="topic.send")
|
|
98
97
|
def publish(self, message: ZMQMessage, topic: str):
|
|
99
98
|
assert isinstance(topic, str), "topic must be a string"
|
|
100
|
-
|
|
101
99
|
with self.pub_lock:
|
|
102
100
|
message.publish_on_topic(self.pub_socket, topic)
|
|
103
101
|
|
|
@@ -109,7 +107,7 @@ class OpenModuleCore(threading.Thread):
|
|
|
109
107
|
self.context.term()
|
|
110
108
|
|
|
111
109
|
|
|
112
|
-
_core_thread:
|
|
110
|
+
_core_thread: OpenModuleCore | None = None
|
|
113
111
|
|
|
114
112
|
|
|
115
113
|
def sigterm_handler(*_):
|
|
@@ -137,7 +135,7 @@ def print_environment(core: OpenModuleCore):
|
|
|
137
135
|
|
|
138
136
|
|
|
139
137
|
def init_openmodule(config, *, dsn: str = None, sentry=None, logging=True, dsgvo=True,
|
|
140
|
-
health_handler:
|
|
138
|
+
health_handler: HealthHandlerType | None = None,
|
|
141
139
|
context=None, database=False, catch_sigterm=True,
|
|
142
140
|
dispatcher_max_threads=1, wait_for_broker=True, **sentry_kwargs) -> OpenModuleCore:
|
|
143
141
|
if health_handler:
|
|
@@ -227,8 +225,7 @@ def shutdown_openmodule():
|
|
|
227
225
|
os._exit(99)
|
|
228
226
|
|
|
229
227
|
if not (current_core.config.TESTING or current_core.config.DEBUG):
|
|
230
|
-
last_will_thread = threading.Thread(target=last_will)
|
|
231
|
-
last_will_thread.setDaemon(True)
|
|
228
|
+
last_will_thread = threading.Thread(target=last_will, daemon=True)
|
|
232
229
|
last_will_thread.start()
|
|
233
230
|
|
|
234
231
|
current_core.shutdown()
|
|
@@ -3,30 +3,25 @@ from datetime import datetime
|
|
|
3
3
|
import orjson
|
|
4
4
|
from sqlalchemy import DateTime
|
|
5
5
|
from sqlalchemy import VARCHAR
|
|
6
|
-
from sqlalchemy.sql.visitors import VisitableType
|
|
7
6
|
from sqlalchemy.types import TypeDecorator
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class
|
|
9
|
+
class CustomTypeImportRegistration(type):
|
|
11
10
|
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
and package info classes
|
|
11
|
+
This metaclass is used to register custom types with their module names.
|
|
12
|
+
This is used in generating alembic migrations.
|
|
15
13
|
"""
|
|
16
|
-
|
|
17
14
|
def __new__(cls, name, bases, dct):
|
|
18
15
|
x = super().__new__(cls, name, bases, dct)
|
|
19
16
|
|
|
20
|
-
# EventModel
|
|
21
17
|
if len(bases) == 1:
|
|
22
18
|
if not getattr(bases[0], "_registry", None):
|
|
23
19
|
setattr(bases[0], "_registry", dict())
|
|
24
|
-
|
|
25
20
|
bases[0]._registry[x] = x.__module__
|
|
26
21
|
return x
|
|
27
22
|
|
|
28
23
|
|
|
29
|
-
class CustomType(TypeDecorator, metaclass=
|
|
24
|
+
class CustomType(TypeDecorator, metaclass=CustomTypeImportRegistration):
|
|
30
25
|
@classmethod
|
|
31
26
|
def custom_import(cls, obj):
|
|
32
27
|
for custom, mod in cls._registry.items():
|
|
@@ -37,6 +32,7 @@ class CustomType(TypeDecorator, metaclass=MetaOptions):
|
|
|
37
32
|
|
|
38
33
|
class TZDateTime(CustomType):
|
|
39
34
|
impl = DateTime
|
|
35
|
+
cache_ok = True
|
|
40
36
|
|
|
41
37
|
def process_bind_param(self, value, dialect):
|
|
42
38
|
if value is not None:
|
|
@@ -48,6 +44,7 @@ class TZDateTime(CustomType):
|
|
|
48
44
|
|
|
49
45
|
class JSONEncodedDict(CustomType):
|
|
50
46
|
impl = VARCHAR
|
|
47
|
+
cache_ok = True
|
|
51
48
|
|
|
52
49
|
def process_bind_param(self, value, dialect):
|
|
53
50
|
if value is not None:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from logging.config import fileConfig
|
|
2
2
|
|
|
3
3
|
from alembic import context
|
|
4
|
-
from sqlalchemy import engine_from_config
|
|
4
|
+
from sqlalchemy import engine_from_config, text
|
|
5
5
|
from sqlalchemy import pool
|
|
6
6
|
|
|
7
7
|
from openmodule.database.custom_types import CustomType
|
|
@@ -55,7 +55,7 @@ def run_migrations_online():
|
|
|
55
55
|
with context.begin_transaction():
|
|
56
56
|
context.run_migrations()
|
|
57
57
|
|
|
58
|
-
connection.execute("PRAGMA foreign_keys=ON")
|
|
58
|
+
connection.execute(text("PRAGMA foreign_keys=ON"))
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
if context.is_offline_mode():
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import datetime
|
|
2
1
|
import os
|
|
3
2
|
import shutil
|
|
4
3
|
import sys
|
|
@@ -11,9 +10,10 @@ from alembic.config import Config
|
|
|
11
10
|
from alembic.operations import Operations, MigrateOperation
|
|
12
11
|
from alembic.runtime.migration import MigrationContext
|
|
13
12
|
|
|
14
|
-
from sqlalchemy import MetaData, DateTime
|
|
13
|
+
from sqlalchemy import MetaData, DateTime, inspect, text
|
|
15
14
|
from sqlalchemy.engine import Engine
|
|
16
|
-
|
|
15
|
+
|
|
16
|
+
from openmodule.utils.misc_functions import utcnow
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@Operations.register_operation("pre_upgrade")
|
|
@@ -22,7 +22,7 @@ class PreUpgradeOp(MigrateOperation):
|
|
|
22
22
|
def pre_upgrade(cls, operations, **kw):
|
|
23
23
|
migration_context: MigrationContext = operations.migration_context
|
|
24
24
|
basename, _ = os.path.splitext(os.path.basename(migration_context.connection.engine.url.database))
|
|
25
|
-
timestamp =
|
|
25
|
+
timestamp = utcnow().strftime('%Y%m%d%H%M%S')
|
|
26
26
|
migration_revision = migration_context.get_current_revision()
|
|
27
27
|
filename = f"{basename}_{timestamp}_{migration_revision}.sqlite3.backup"
|
|
28
28
|
|
|
@@ -78,12 +78,12 @@ def pre_upgrade(operations, operation):
|
|
|
78
78
|
# NOTE: This is currently in sync with pre_downgrade, if you want to have
|
|
79
79
|
# different behavior, you'll need to change th pre_downgrade function below
|
|
80
80
|
conn = operations.get_bind()
|
|
81
|
-
inspector =
|
|
81
|
+
inspector = inspect(conn)
|
|
82
82
|
tables = inspector.get_table_names()
|
|
83
83
|
for table in tables:
|
|
84
84
|
if table.startswith("_alembic_tmp_"):
|
|
85
85
|
operations.drop_table(table)
|
|
86
|
-
operations.execute("PRAGMA foreign_keys
|
|
86
|
+
operations.execute(text("PRAGMA foreign_keys=OFF"))
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@Operations.implementation_for(PostUpgradeOp)
|
|
@@ -139,14 +139,15 @@ def alembic_config(connection: Engine, alembic_path: str):
|
|
|
139
139
|
return alembic_cfg
|
|
140
140
|
|
|
141
141
|
|
|
142
|
-
def migrate_database(
|
|
142
|
+
def migrate_database(engine: Engine, alembic_path: Optional[str] = None):
|
|
143
143
|
if alembic_path is None:
|
|
144
144
|
alembic_path = os.path.join(os.getcwd(), "database")
|
|
145
145
|
assert os.path.exists(os.path.abspath(alembic_path)), f"alembic path {os.path.abspath(alembic_path)} does not exist"
|
|
146
|
-
config = alembic_config(
|
|
146
|
+
config = alembic_config(engine, alembic_path)
|
|
147
147
|
command.upgrade(config, "head")
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
with engine.connect() as connection:
|
|
150
|
+
check = connection.execute(text("PRAGMA foreign_keys")).fetchone()
|
|
150
151
|
assert check is not None and check[0] == 1, "foreign keys are not enabled"
|
|
151
152
|
|
|
152
153
|
|
|
@@ -167,7 +168,7 @@ def register_bases(bases, show_deprecation_warning=True):
|
|
|
167
168
|
for table in base.metadata.tables.values():
|
|
168
169
|
for x in table.columns:
|
|
169
170
|
check_invalid_database_column_type(x.type)
|
|
170
|
-
table.
|
|
171
|
+
table.to_metadata(target_metadata)
|
|
171
172
|
context.config.attributes["target_metadata"] = target_metadata
|
|
172
173
|
|
|
173
174
|
|
|
@@ -8,10 +8,11 @@ from concurrent.futures._base import Executor
|
|
|
8
8
|
from concurrent.futures.process import ProcessPoolExecutor
|
|
9
9
|
from concurrent.futures.thread import ThreadPoolExecutor
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import
|
|
11
|
+
from typing import Callable, DefaultDict, TypeVar, Generic
|
|
12
12
|
|
|
13
|
+
from pydantic_core import PydanticUndefined
|
|
13
14
|
import zmq
|
|
14
|
-
from pydantic import ValidationError, BaseModel
|
|
15
|
+
from pydantic import ValidationError, BaseModel
|
|
15
16
|
from sentry_sdk.utils import qualname_from_function
|
|
16
17
|
|
|
17
18
|
from openmodule import sentry
|
|
@@ -41,14 +42,14 @@ class DummyExecutor(Executor):
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
class Listener:
|
|
44
|
-
def __init__(self, message_class:
|
|
45
|
+
def __init__(self, message_class: type[ZMQMessage], type: str | None, filter: Callable | None,
|
|
45
46
|
handler: Callable):
|
|
46
47
|
self.filter = filter
|
|
47
48
|
self.handler = sentry.trace(f"message_handler.{qualname_from_function(handler)}")(handler)
|
|
48
49
|
self.type = type
|
|
49
50
|
self.message_class = message_class
|
|
50
51
|
|
|
51
|
-
def matches(self, message:
|
|
52
|
+
def matches(self, message: dict):
|
|
52
53
|
if self.type and message.get("type") != self.type:
|
|
53
54
|
return False
|
|
54
55
|
|
|
@@ -66,7 +67,7 @@ class EventListener(Generic[EventArgs], list):
|
|
|
66
67
|
note: the generic may not work as intended, but it is nevertheless a nice way to document the event
|
|
67
68
|
handler arguments
|
|
68
69
|
"""
|
|
69
|
-
log:
|
|
70
|
+
log: logging.Logger | None = None
|
|
70
71
|
|
|
71
72
|
def __init__(self, *args, log=None, raise_exceptions=False):
|
|
72
73
|
super().__init__(args)
|
|
@@ -91,7 +92,7 @@ ZMQMessageSub = TypeVar('ZMQMessageSub', bound=ZMQMessage)
|
|
|
91
92
|
|
|
92
93
|
class MessageDispatcher:
|
|
93
94
|
def __init__(self, name=None, *, raise_validation_errors=False, raise_handler_errors=False,
|
|
94
|
-
executor:
|
|
95
|
+
executor: Executor | None = None):
|
|
95
96
|
"""
|
|
96
97
|
:param name: optionally name the dispatcher for logging purposes
|
|
97
98
|
:param raise_validation_errors: if true and received messages do not match a validation error is raised,
|
|
@@ -106,7 +107,7 @@ class MessageDispatcher:
|
|
|
106
107
|
|
|
107
108
|
self.name = name
|
|
108
109
|
self.log = logging.getLogger(f"{self.__class__.__name__}({self.name})")
|
|
109
|
-
self.listeners: DefaultDict[str,
|
|
110
|
+
self.listeners: DefaultDict[str, list[Listener]] = defaultdict(list)
|
|
110
111
|
self.raise_validation_errors = raise_validation_errors
|
|
111
112
|
self.raise_handler_errors = raise_handler_errors
|
|
112
113
|
self.executor = executor or DummyExecutor()
|
|
@@ -152,9 +153,9 @@ class MessageDispatcher:
|
|
|
152
153
|
return False
|
|
153
154
|
|
|
154
155
|
def register_handler(self, topic: str,
|
|
155
|
-
message_class:
|
|
156
|
+
message_class: type[ZMQMessageSub],
|
|
156
157
|
handler: Callable[[ZMQMessageSub], None], *,
|
|
157
|
-
filter:
|
|
158
|
+
filter: dict | Callable[[dict], bool] | None = None,
|
|
158
159
|
match_type=True,
|
|
159
160
|
register_schema=True):
|
|
160
161
|
"""
|
|
@@ -169,16 +170,18 @@ class MessageDispatcher:
|
|
|
169
170
|
assert isinstance(topic, str), "topic must be a string"
|
|
170
171
|
|
|
171
172
|
if match_type:
|
|
172
|
-
|
|
173
|
+
if valid_type := "type" in message_class.model_fields:
|
|
174
|
+
valid_type &= message_class.model_fields["type"].default is not PydanticUndefined
|
|
175
|
+
assert valid_type, (
|
|
173
176
|
"\n\nYour message class definition does not set a `type` field, or the type field "
|
|
174
177
|
"does not have a default value! To receive all message type pass `match_type=False` to "
|
|
175
178
|
"`register_handler`. Otherwise please define a `type` for your message class."
|
|
176
179
|
)
|
|
177
|
-
|
|
180
|
+
type_ = message_class.model_fields["type"].default
|
|
178
181
|
else:
|
|
179
|
-
|
|
182
|
+
type_ = None
|
|
180
183
|
|
|
181
|
-
listener = Listener(message_class,
|
|
184
|
+
listener = Listener(message_class, type_, filter, handler)
|
|
182
185
|
self.listeners[topic].append(listener)
|
|
183
186
|
|
|
184
187
|
if register_schema and not self._is_test_handler(handler):
|
|
@@ -186,7 +189,7 @@ class MessageDispatcher:
|
|
|
186
189
|
|
|
187
190
|
return listener
|
|
188
191
|
|
|
189
|
-
def dispatch(self, topic: str, message:
|
|
192
|
+
def dispatch(self, topic: str, message: dict | BaseModel):
|
|
190
193
|
with self._shutdown_lock:
|
|
191
194
|
if self._shutdown:
|
|
192
195
|
# We need to drop messages after shutdown somewhere.
|
|
@@ -197,7 +200,7 @@ class MessageDispatcher:
|
|
|
197
200
|
assert isinstance(topic, str), "topic must be a string"
|
|
198
201
|
|
|
199
202
|
if isinstance(message, BaseModel):
|
|
200
|
-
message = message.
|
|
203
|
+
message = message.model_dump()
|
|
201
204
|
|
|
202
205
|
listeners = self.listeners.get(topic, [])
|
|
203
206
|
for listener in listeners:
|
|
@@ -205,11 +208,11 @@ class MessageDispatcher:
|
|
|
205
208
|
message.update(sentry.get_trace_headers())
|
|
206
209
|
self.executor.submit(self.execute, topic, listener, message)
|
|
207
210
|
|
|
208
|
-
def execute(self, topic: str, listener: Listener, message:
|
|
211
|
+
def execute(self, topic: str, listener: Listener, message: dict):
|
|
209
212
|
with sentry.continue_trace_zmq_message_process(
|
|
210
213
|
topic, message, force_new_transaction=self._new_transactions):
|
|
211
214
|
try:
|
|
212
|
-
parsed_message =
|
|
215
|
+
parsed_message = listener.message_class.model_validate(message)
|
|
213
216
|
except ValidationError as e:
|
|
214
217
|
if self.raise_validation_errors:
|
|
215
218
|
raise e from None
|
|
@@ -229,17 +232,17 @@ class MessageDispatcher:
|
|
|
229
232
|
|
|
230
233
|
class SubscribingMessageDispatcher(MessageDispatcher):
|
|
231
234
|
def __init__(self, subscribe: Callable[[str], None], name=None, *, raise_validation_errors=False,
|
|
232
|
-
raise_handler_errors=False, unsubscribe:
|
|
233
|
-
executor:
|
|
235
|
+
raise_handler_errors=False, unsubscribe: Callable[[str], None] | None = None,
|
|
236
|
+
executor: Executor | None = None):
|
|
234
237
|
super().__init__(name=name, raise_validation_errors=raise_validation_errors,
|
|
235
238
|
raise_handler_errors=raise_handler_errors, executor=executor)
|
|
236
239
|
self.subscribe = subscribe
|
|
237
240
|
self.unsubscribe = unsubscribe
|
|
238
241
|
|
|
239
242
|
def register_handler(self, topic: str,
|
|
240
|
-
message_class:
|
|
243
|
+
message_class: type[ZMQMessageSub],
|
|
241
244
|
handler: Callable[[ZMQMessageSub], None], *,
|
|
242
|
-
filter:
|
|
245
|
+
filter: dict | None = None,
|
|
243
246
|
register_schema=True,
|
|
244
247
|
match_type=True):
|
|
245
248
|
assert isinstance(topic, str), "channel must be a string"
|
|
@@ -268,7 +271,7 @@ class SubscribingMessageDispatcher(MessageDispatcher):
|
|
|
268
271
|
|
|
269
272
|
class ZMQMessageDispatcher(SubscribingMessageDispatcher):
|
|
270
273
|
def __init__(self, sub_socket: zmq.Socket, name=None, *, raise_validation_errors=False, raise_handler_errors=False,
|
|
271
|
-
executor:
|
|
274
|
+
executor: Executor | None = None):
|
|
272
275
|
super().__init__(
|
|
273
276
|
subscribe=lambda x: sub_socket.subscribe(x.encode("utf8")),
|
|
274
277
|
unsubscribe=lambda x: sub_socket.unsubscribe(x.encode("utf8")),
|
|
@@ -280,8 +283,8 @@ class ZMQMessageDispatcher(SubscribingMessageDispatcher):
|
|
|
280
283
|
|
|
281
284
|
|
|
282
285
|
class DeeplogMessageDispatcher(MessageDispatcher):
|
|
283
|
-
def __init__(self, path:
|
|
284
|
-
executor:
|
|
286
|
+
def __init__(self, path: Path | str, name=None, *, raise_validation_errors=False, raise_handler_errors=False,
|
|
287
|
+
executor: Executor | None = None):
|
|
285
288
|
super().__init__(name, raise_validation_errors=raise_validation_errors,
|
|
286
289
|
raise_handler_errors=raise_handler_errors, executor=executor)
|
|
287
290
|
if not isinstance(path, Path):
|