exobrain-database 0.2.0__tar.gz → 0.3.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.
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/PKG-INFO +46 -27
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/README.md +43 -17
- exobrain_database-0.3.0/pyproject.toml +113 -0
- exobrain_database-0.2.0/pyproject.toml → exobrain_database-0.3.0/pyproject.toml.orig +16 -4
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/__init__.py +1 -1
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/alembic.ini +1 -1
- exobrain_database-0.3.0/src/exobrain/database/migrations/cli.py +72 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/env.py +30 -23
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/migration_manager.py +5 -1
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_04_20_1015-8f3c5e2d9a1b_add_running_action_summary_table_with_text_column.py +2 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_04_30_1357-c3e8047f29f6_add_kpi_names_to_predefined_action.py +1 -1
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_07_22_1210-f1a2b3c4d5e6_add_reporting_field_tables.py +132 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_04_1241-d4e8f2a6b1c3_add_editable_fields_to_action_conf.py +36 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1508-de9cdd9d1f23_convert_running_status_columns_to_postgres_enums.py +209 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1510-102986454ad1_migrate_deprecated_running_statuses.py +297 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1512-9e35d31c23bf_drop_deprecated_running_status_enum_values.py +271 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1514-a7f3c21d8b04_add_running_status_timestamps.py +79 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_08_06_1620-b8d47a1c9e02_migrate_widget_conf_deprecated_statuses.py +419 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_03_0910-c1f7a4be3d58_add_org_stop_risk_role_and_permission.py +239 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_03_0915-a3d92c07fb14_add_stop_risk_params_to_action_conf.py +105 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_07_1000-cf5954e2447b_move_stop_risk_params_to_risk_conf.py +181 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_07_1005-dde1d89b4372_add_stop_risk_snapshot_to_running_risk.py +127 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_09_0910-f7d0d5c816d5_store_running_action_kpis_in_kpi_mapping.py +180 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_11_0900-01c09dcf16bd_add_running_action_error_table.py +183 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_11_1100-e21b7f4a9c86_remove_error_data_scopes.py +130 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_17_1400-035a82018e8a_add_ctx_element_indexes_to_running_risk.py +61 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_19_1500-5a24d1db4aee_add_running_action_category_table.py +146 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_09_23_1656-cb0f9bd0b7e6_create_trans_table.py +55 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_10_01_1000-b29a8020ead0_add_org_export_risk_role_and_permission.py +240 -0
- exobrain_database-0.3.0/src/exobrain/database/migrations/versions/2026_10_02_1000-7b2d4f1c9a60_add_running_risk_sequence.py +111 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/base.py +9 -4
- exobrain_database-0.3.0/src/exobrain/database/model/enums/__init__.py +21 -0
- exobrain_database-0.3.0/src/exobrain/database/model/enums/config.py +61 -0
- exobrain_database-0.3.0/src/exobrain/database/model/enums/context.py +20 -0
- exobrain_database-0.3.0/src/exobrain/database/model/enums/reporting.py +15 -0
- exobrain_database-0.3.0/src/exobrain/database/model/enums/running.py +104 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/field_types.py +3 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/copilot.py +1 -1
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/organization_models.py +4 -4
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/predefined_models.py +6 -6
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/reason_models.py +18 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/__init__.py +9 -4
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/config_models.py +58 -4
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/dashboard_models.py +2 -2
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/org_base.py +1 -1
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/organization_settings.py +3 -3
- exobrain_database-0.3.0/src/exobrain/database/model/org/report_models.py +135 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/running_models.py +453 -45
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/scope.py +10 -10
- exobrain_database-0.3.0/src/exobrain/database/model/org/trans.py +44 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/user.py +3 -3
- exobrain_database-0.3.0/src/exobrain/database/tools/report_field_coercion.py +64 -0
- exobrain_database-0.3.0/src/exobrain/database/tools/risk_report_projector.py +180 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/sql_query_logger.py +5 -5
- exobrain_database-0.2.0/src/exobrain/database/model/enums/__init__.py +0 -15
- exobrain_database-0.2.0/src/exobrain/database/model/enums/config.py +0 -30
- exobrain_database-0.2.0/src/exobrain/database/model/enums/running.py +0 -87
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/LICENSE.md +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/__init__.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/README.md +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/script.py.mako +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_08_17_0937-3ed3cf31c9d4_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_08_31_1322-aa6854636eac_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_01_0925-9667f0608380_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_13_1243-3cd1eb0d7b52_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_15_1447-52f33bc03521_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_19_0956-f8e096a41120_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_21_1642-74f18c0bab6e_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_09_28_1237-919ce06afab1_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_04_0718-03535f8dfe5f_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_05_1508-f64d4c00b610_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_06_0819-e544518a415c_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_06_1312-b9b232d63be3_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_25_0902-aab08fb68941_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_10_25_0937-d59ec80e6dd7_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_22_1628-84b116f3df26_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_22_1654-bcb01e365c42_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_27_1045-00ce519af235_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_27_1048-f779dc9fe429_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_11_29_1421-ad2b4c9c38fe_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_04_1029-f91d936478fb_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_11_1104-b33e0d6a5bdd_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2023_12_18_1406-73ac94585923_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_05_1022-f231770c573e_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_17_1606-b94c145b2310_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_18_1547-c450c961dfd0_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_18_1855-7101980bc238_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_01_22_1616-a35a2828dbcd_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_04_1549-4cc4ffdb6c02_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_13_1323-97a9ef3f38c3_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_20_1033-13bc4d2ab3ab_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_28_0905-ffd01ebb2c87_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_03_28_1332-33744d8620d3_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_04_05_0919-a14d98908583_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_04_29_1515-882409414d37_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_05_23_0959-24bb8fdb3ba7_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_05_24_1248-f2a78a625a74_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_06_07_1537-004b611f77cf_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_06_10_1306-f0fe99d57963_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2024_10_15_0646-ef0829fe3540_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_01_28_1020-ea2ebd0e2cdc_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_03_19_1341-adeeb7c46a3c_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_03_25_1449-8fb5b2059d5a_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5-org.json +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5-public.json +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_06_1503-88aa2ef323c5_add_constraints_to_fk.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_20_1302-37f7dbf56615_add_is_learning_field_to_license.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_05_21_0839-096c1ab6ea15_add_is_learning_field_to_predefined_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_03_0336-60d91382b626_add_grace_period_field_to_risk_conf.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_17_1013-4894e248a31d_add_risk_conf_buffer_period_field_to_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_20_0845-c0e0c905cfb1_add_computing_strategy.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_20_0919-360b6879ae25_add_fully_computed_field_to_running_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_21_1200-1a37475a962d_fix_feasible_field_in_running_risk_table_set_not_null.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_21_1300-d456be82025a_add_computed_mapping_field_in_running_.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0154-317d388748a1_adding_auto_rejected_reason_code.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0227-0a9522eb04f0_update_predefined_actions_execution.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0610-9daee7d935b1_add_rejection_and_expiration_fields.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_27_0617-ee6062e6dc4d_add_rejection_and_expiration_fields.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_06_29_0828-90923eeab038_calculate_due_dates_and_due_indicators.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_09_26_1624-2716d77c7904_make_context_fields_non_nullable.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_09_26_1857-0ab6e7d1a127_add_note_column_to_running_action.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_10_17_1620-6400ea4ce6f0_add_index_overdue_risks.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_10_31_0222-67c46f78caca_convert_action_context_data_json_to_jsonb.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2025_11_04_2117-a8a814d7f2ea_rename_execution_reason_code.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_04_1647-87c0d5fd2688_apply_new_naming_rules_for_indexes.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_04_1801-392b727bbaa1_remove_unused_exo_conf_table.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0840-4b12100a932c_add_constraints_to_organizations_settings.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0917-f67bd91a1913_change_copilot_uiConfiguration_json_to_jsonb.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_0935-87de8335f045_constrain_organizations_preferences_fields.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1018-7271b6d49e2c_enforce_not_null_and_jsonb_for_predefined_tables.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1510-711567521aa6_convert_config_tables_json_to_jsonb.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_05_1540-ce5a35090a82_convert_connection_json_to_jsonb.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_0939-115812c0bcd6_make_scope_key_non_nullable.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_1109-7dd6b5f271ed_convert_json_to_jsonb_for_dashboard_and_widgets.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_06_1452-4e4ad858fdf9_convert_json_to_jsonb_for_running_entities.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_09_1558-6954766729aa_simplify_one_to_many_relationships.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_01_12_1639-e548f437e5de_simplify_one_to_many_relationships.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_03_1456-abbb5a630567_simplify_one_to_many_relationships.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_06_0827-95438a5ec210_simplify_one_to_many_relationships.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_02_06_0835-881f104f8b2b_simplify_one_to_many_relationships.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_05_07_0100-a1b2c3d4e5f6_create_scores_table.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_06_29_1324-b23761c01aac_add_updated_data_to_running_action_context.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/migrations/versions/2026_06_29_1500-c5a9e1f3b7d2_add_widget_executive_view_fields.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/__init__.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/__init__.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/action_conf_action_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/copilot_license.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/exec_conf_execution_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_action_action_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_action_predefined_risk.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_execution_execution_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_execution_predefined_action.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/predefined_risk_risk_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/risk_conf_risk_reason.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_action_conf.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_exec_conf.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_permissions.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_predefined_action.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_predefined_execution.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_running_actions.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_running_executions.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/roles_users.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/running_action_context_scopes.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/associations/users_scopes.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/enums/currency.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/enums/dashboard.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/__init__.py +2 -2
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/general_base.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/permission.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/general/role.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/model/org/connection.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/py.typed +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/__init__.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/jsonb_filter.py +0 -0
- {exobrain_database-0.2.0 → exobrain_database-0.3.0}/src/exobrain/database/tools/record_count.py +0 -0
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: exobrain-database
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Exobrain database model and migration management
|
|
5
5
|
Keywords:
|
|
6
6
|
Author: Laurent LAPORTE
|
|
7
7
|
Author-email: Laurent LAPORTE <laurent@dfya.io>
|
|
8
|
-
License:
|
|
9
|
-
|
|
10
|
-
This is a private project.
|
|
11
|
-
All rights reserved.
|
|
12
|
-
|
|
13
|
-
The content of this repository is intended for private use only.
|
|
14
|
-
Reproduction, distribution, or disclosure to third parties, in whole or in part, is strictly prohibited without the explicit written permission of the copyright holder.
|
|
8
|
+
License-File: LICENSE.md
|
|
15
9
|
Classifier: Development Status :: 4 - Beta
|
|
16
10
|
Classifier: Programming Language :: Python
|
|
17
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -20,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
20
14
|
Classifier: Topic :: Software Development :: Libraries
|
|
21
15
|
Classifier: Topic :: Database
|
|
22
16
|
Classifier: Topic :: Database :: Database Engines/Servers
|
|
23
|
-
Classifier: License :: Other/Proprietary License
|
|
24
17
|
Requires-Dist: alembic>=1.18.4
|
|
25
18
|
Requires-Dist: psycopg[binary]>=3.3.4
|
|
26
19
|
Requires-Dist: sqlalchemy>=2.0.51
|
|
@@ -134,6 +127,29 @@ For creating a new migration, pass `-c` explicitly so the file naming template f
|
|
|
134
127
|
alembic -c src/exobrain/database/migrations/alembic.ini revision --autogenerate -m "short description"
|
|
135
128
|
```
|
|
136
129
|
|
|
130
|
+
#### Running migrations from outside this repository
|
|
131
|
+
|
|
132
|
+
The `alembic` CLI above only works from this project's root, since it relies on the `[tool.alembic]`
|
|
133
|
+
section of this repo's `pyproject.toml`. Consuming projects (e.g. `exobrain-server`) or containers that
|
|
134
|
+
only have `exobrain-database` installed as a dependency don't have that file, and the packaged
|
|
135
|
+
`alembic.ini` sits inside the installed package (e.g.: under `.venv/`), which is impractical to locate.
|
|
136
|
+
|
|
137
|
+
For that case, `exobrain-database` ships a console script, `exobrain-db-migrate`, that resolves its own
|
|
138
|
+
`alembic.ini` and wraps the full Alembic CLI, so it works the same way from any environment where the
|
|
139
|
+
package is installed:
|
|
140
|
+
|
|
141
|
+
```console
|
|
142
|
+
exobrain-db-migrate current # Show applied revision(s)
|
|
143
|
+
exobrain-db-migrate history # List migration history
|
|
144
|
+
exobrain-db-migrate upgrade head # Apply all pending migrations
|
|
145
|
+
exobrain-db-migrate downgrade -1 # Roll back one migration
|
|
146
|
+
exobrain-db-migrate -x schema=org_42 current # Target a single organization schema
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
It requires the same `SQL_*` environment variables as above, and writes its logs to `stdout` so they are
|
|
150
|
+
picked up by container log collectors. It is a thin wrapper: any other native Alembic command
|
|
151
|
+
(`stamp`, `heads`, `show`, `-c`/`ALEMBIC_CONFIG` override, ...) works unchanged.
|
|
152
|
+
|
|
137
153
|
---
|
|
138
154
|
|
|
139
155
|
## Project Structure
|
|
@@ -142,23 +158,26 @@ The source code lives under `src/exobrain/database/` as a namespace package:
|
|
|
142
158
|
|
|
143
159
|
```
|
|
144
160
|
src/exobrain/database/
|
|
145
|
-
├── migrations/
|
|
146
|
-
│ ├── alembic.ini
|
|
147
|
-
│ ├──
|
|
148
|
-
│ ├──
|
|
149
|
-
│
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
│ ├──
|
|
153
|
-
│ ├──
|
|
154
|
-
│ ├──
|
|
155
|
-
│
|
|
156
|
-
│
|
|
157
|
-
│
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
├──
|
|
161
|
-
|
|
161
|
+
├── migrations/ # Alembic migration engine
|
|
162
|
+
│ ├── alembic.ini # Alembic configuration file
|
|
163
|
+
│ ├── cli.py # `exobrain-db-migrate` console script entry point
|
|
164
|
+
│ ├── env.py # Migration environment setup
|
|
165
|
+
│ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
|
|
166
|
+
│ └── versions/ # Auto-generated migration scripts
|
|
167
|
+
├── model/ # SQLAlchemy ORM models
|
|
168
|
+
│ ├── base.py # Declarative base classes
|
|
169
|
+
│ ├── associations/ # Many-to-many association tables
|
|
170
|
+
│ ├── enums/ # Database enumeration types (config, currency, running states)
|
|
171
|
+
│ ├── general/ # Cross-organization models (copilots, permissions, roles,
|
|
172
|
+
│ │ # predefined actions/executions/risks, reasons)
|
|
173
|
+
│ └── org/ # Per-organization models (config, connections, dashboards,
|
|
174
|
+
│ # running actions/executions/risks, scopes, users)
|
|
175
|
+
└── tools/ # Reusable database utilities
|
|
176
|
+
├── jsonb_filter.py # Helper for filtering on JSONB columns
|
|
177
|
+
├── record_count.py # Efficient record counting queries
|
|
178
|
+
├── report_field_coercion.py # Coerce raw context values into typed report slots
|
|
179
|
+
├── risk_report_projector.py # Project declared reporting fields into risk_report_fact
|
|
180
|
+
└── sql_query_logger.py # SQLAlchemy query logging utility
|
|
162
181
|
```
|
|
163
182
|
|
|
164
183
|
### Key design decisions
|
|
@@ -102,6 +102,29 @@ For creating a new migration, pass `-c` explicitly so the file naming template f
|
|
|
102
102
|
alembic -c src/exobrain/database/migrations/alembic.ini revision --autogenerate -m "short description"
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
#### Running migrations from outside this repository
|
|
106
|
+
|
|
107
|
+
The `alembic` CLI above only works from this project's root, since it relies on the `[tool.alembic]`
|
|
108
|
+
section of this repo's `pyproject.toml`. Consuming projects (e.g. `exobrain-server`) or containers that
|
|
109
|
+
only have `exobrain-database` installed as a dependency don't have that file, and the packaged
|
|
110
|
+
`alembic.ini` sits inside the installed package (e.g.: under `.venv/`), which is impractical to locate.
|
|
111
|
+
|
|
112
|
+
For that case, `exobrain-database` ships a console script, `exobrain-db-migrate`, that resolves its own
|
|
113
|
+
`alembic.ini` and wraps the full Alembic CLI, so it works the same way from any environment where the
|
|
114
|
+
package is installed:
|
|
115
|
+
|
|
116
|
+
```console
|
|
117
|
+
exobrain-db-migrate current # Show applied revision(s)
|
|
118
|
+
exobrain-db-migrate history # List migration history
|
|
119
|
+
exobrain-db-migrate upgrade head # Apply all pending migrations
|
|
120
|
+
exobrain-db-migrate downgrade -1 # Roll back one migration
|
|
121
|
+
exobrain-db-migrate -x schema=org_42 current # Target a single organization schema
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
It requires the same `SQL_*` environment variables as above, and writes its logs to `stdout` so they are
|
|
125
|
+
picked up by container log collectors. It is a thin wrapper: any other native Alembic command
|
|
126
|
+
(`stamp`, `heads`, `show`, `-c`/`ALEMBIC_CONFIG` override, ...) works unchanged.
|
|
127
|
+
|
|
105
128
|
---
|
|
106
129
|
|
|
107
130
|
## Project Structure
|
|
@@ -110,23 +133,26 @@ The source code lives under `src/exobrain/database/` as a namespace package:
|
|
|
110
133
|
|
|
111
134
|
```
|
|
112
135
|
src/exobrain/database/
|
|
113
|
-
├── migrations/
|
|
114
|
-
│ ├── alembic.ini
|
|
115
|
-
│ ├──
|
|
116
|
-
│ ├──
|
|
117
|
-
│
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
│ ├──
|
|
121
|
-
│ ├──
|
|
122
|
-
│ ├──
|
|
123
|
-
│
|
|
124
|
-
│
|
|
125
|
-
│
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
├──
|
|
129
|
-
|
|
136
|
+
├── migrations/ # Alembic migration engine
|
|
137
|
+
│ ├── alembic.ini # Alembic configuration file
|
|
138
|
+
│ ├── cli.py # `exobrain-db-migrate` console script entry point
|
|
139
|
+
│ ├── env.py # Migration environment setup
|
|
140
|
+
│ ├── migration_manager.py # Public API: upgrade / downgrade per org schema
|
|
141
|
+
│ └── versions/ # Auto-generated migration scripts
|
|
142
|
+
├── model/ # SQLAlchemy ORM models
|
|
143
|
+
│ ├── base.py # Declarative base classes
|
|
144
|
+
│ ├── associations/ # Many-to-many association tables
|
|
145
|
+
│ ├── enums/ # Database enumeration types (config, currency, running states)
|
|
146
|
+
│ ├── general/ # Cross-organization models (copilots, permissions, roles,
|
|
147
|
+
│ │ # predefined actions/executions/risks, reasons)
|
|
148
|
+
│ └── org/ # Per-organization models (config, connections, dashboards,
|
|
149
|
+
│ # running actions/executions/risks, scopes, users)
|
|
150
|
+
└── tools/ # Reusable database utilities
|
|
151
|
+
├── jsonb_filter.py # Helper for filtering on JSONB columns
|
|
152
|
+
├── record_count.py # Efficient record counting queries
|
|
153
|
+
├── report_field_coercion.py # Coerce raw context values into typed report slots
|
|
154
|
+
├── risk_report_projector.py # Project declared reporting fields into risk_report_fact
|
|
155
|
+
└── sql_query_logger.py # SQLAlchemy query logging utility
|
|
130
156
|
```
|
|
131
157
|
|
|
132
158
|
### Key design decisions
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.11.23,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "exobrain-database"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Exobrain database model and migration management"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license-files = ["LICENSE.md"]
|
|
12
|
+
keywords = []
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Programming Language :: Python",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3.13",
|
|
18
|
+
"Programming Language :: Python :: 3.14",
|
|
19
|
+
"Topic :: Software Development :: Libraries",
|
|
20
|
+
"Topic :: Database",
|
|
21
|
+
"Topic :: Database :: Database Engines/Servers",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"alembic>=1.18.4",
|
|
25
|
+
"psycopg[binary]>=3.3.4",
|
|
26
|
+
"sqlalchemy>=2.0.51",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[[project.authors]]
|
|
30
|
+
name = "Laurent LAPORTE"
|
|
31
|
+
email = "laurent@dfya.io"
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Documentation = "https://github.com/MyExobrain/exobrain-database#readme"
|
|
35
|
+
Issues = "https://github.com/MyExobrain/exobrain-database/issues"
|
|
36
|
+
Source = "https://github.com/MyExobrain/exobrain-database"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
exobrain-db-migrate = "exobrain.database.migrations.cli:main"
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
dev = [
|
|
43
|
+
"coverage>=7.14.2",
|
|
44
|
+
"mkdocs>=1.6.1",
|
|
45
|
+
"mkdocs-material>=9.6.0",
|
|
46
|
+
"mypy>=2.1.0",
|
|
47
|
+
"pytest>=9.1.1",
|
|
48
|
+
"pytest-cov>=7.1.0",
|
|
49
|
+
"twine>=6.2.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.uv.build-backend]
|
|
53
|
+
module-name = "exobrain.database"
|
|
54
|
+
|
|
55
|
+
[tool.coverage.run]
|
|
56
|
+
source_pkgs = [
|
|
57
|
+
"exobrain.database",
|
|
58
|
+
"tests",
|
|
59
|
+
]
|
|
60
|
+
branch = true
|
|
61
|
+
parallel = true
|
|
62
|
+
|
|
63
|
+
[tool.coverage.paths]
|
|
64
|
+
exobrain_database_model = [
|
|
65
|
+
"src/exobrain/database",
|
|
66
|
+
"*/exobrain-database/src/exobrain/database",
|
|
67
|
+
]
|
|
68
|
+
tests = [
|
|
69
|
+
"tests",
|
|
70
|
+
"*/exobrain-database/tests",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[tool.coverage.report]
|
|
74
|
+
exclude_lines = [
|
|
75
|
+
"no cov",
|
|
76
|
+
"if __name__ == .__main__.:",
|
|
77
|
+
"if TYPE_CHECKING:",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[tool.mypy]
|
|
81
|
+
python_version = "3.13"
|
|
82
|
+
namespace_packages = true
|
|
83
|
+
explicit_package_bases = true
|
|
84
|
+
mypy_path = "src"
|
|
85
|
+
ignore_missing_imports = true
|
|
86
|
+
strict = true
|
|
87
|
+
exclude = ["src/exobrain/database/migrations/versions"]
|
|
88
|
+
|
|
89
|
+
[tool.ruff]
|
|
90
|
+
line-length = 120
|
|
91
|
+
indent-width = 4
|
|
92
|
+
target-version = "py312"
|
|
93
|
+
exclude = ["src/exobrain/database/migrations/versions"]
|
|
94
|
+
|
|
95
|
+
[tool.ruff.lint.extend-per-file-ignores]
|
|
96
|
+
"src/exobrain/database/model/*/*.py" = ["TID252"]
|
|
97
|
+
"src/exobrain/database/tools/*.py" = ["TID252"]
|
|
98
|
+
"src/exobrain/database/migrations/versions/*.py" = ["INP001"]
|
|
99
|
+
|
|
100
|
+
[tool.alembic]
|
|
101
|
+
script_location = "src/exobrain/database/migrations"
|
|
102
|
+
|
|
103
|
+
[tool.ty.rules]
|
|
104
|
+
all = "error"
|
|
105
|
+
missing-override-decorator = "ignore"
|
|
106
|
+
unsound-assignment = "ignore"
|
|
107
|
+
unsound-return-statement = "ignore"
|
|
108
|
+
|
|
109
|
+
[tool.ty.src]
|
|
110
|
+
exclude = ["src/exobrain/database/migrations/versions"]
|
|
111
|
+
|
|
112
|
+
[tool.ty.environment]
|
|
113
|
+
python-version = "3.12"
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.11.23,<0.
|
|
2
|
+
requires = ["uv_build>=0.11.23,<0.13"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "exobrain-database"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Exobrain database model and migration management"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Laurent LAPORTE", email = "laurent@dfya.io" }
|
|
11
11
|
]
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.12"
|
|
14
|
-
license =
|
|
14
|
+
license-files = ["LICENSE.md"]
|
|
15
15
|
keywords = []
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Development Status :: 4 - Beta",
|
|
@@ -22,7 +22,6 @@ classifiers = [
|
|
|
22
22
|
"Topic :: Software Development :: Libraries",
|
|
23
23
|
"Topic :: Database",
|
|
24
24
|
"Topic :: Database :: Database Engines/Servers",
|
|
25
|
-
"License :: Other/Proprietary License",
|
|
26
25
|
]
|
|
27
26
|
dependencies = [
|
|
28
27
|
"alembic>=1.18.4",
|
|
@@ -35,9 +34,14 @@ Documentation = "https://github.com/MyExobrain/exobrain-database#readme"
|
|
|
35
34
|
Issues = "https://github.com/MyExobrain/exobrain-database/issues"
|
|
36
35
|
Source = "https://github.com/MyExobrain/exobrain-database"
|
|
37
36
|
|
|
37
|
+
[project.scripts]
|
|
38
|
+
exobrain-db-migrate = "exobrain.database.migrations.cli:main"
|
|
39
|
+
|
|
38
40
|
[dependency-groups]
|
|
39
41
|
dev = [
|
|
40
42
|
"coverage>=7.14.2",
|
|
43
|
+
"mkdocs>=1.6.1",
|
|
44
|
+
"mkdocs-material>=9.6.0",
|
|
41
45
|
"mypy>=2.1.0",
|
|
42
46
|
"pytest>=9.1.1",
|
|
43
47
|
"pytest-cov>=7.1.0",
|
|
@@ -100,6 +104,7 @@ exclude = [
|
|
|
100
104
|
|
|
101
105
|
[tool.ruff.lint.extend-per-file-ignores]
|
|
102
106
|
"src/exobrain/database/model/*/*.py" = ["TID252"]
|
|
107
|
+
"src/exobrain/database/tools/*.py" = ["TID252"]
|
|
103
108
|
"src/exobrain/database/migrations/versions/*.py" = ["INP001"]
|
|
104
109
|
|
|
105
110
|
|
|
@@ -119,6 +124,13 @@ script_location = "src/exobrain/database/migrations"
|
|
|
119
124
|
[tool.ty.rules]
|
|
120
125
|
all = "error"
|
|
121
126
|
missing-override-decorator = "ignore"
|
|
127
|
+
# SQLAlchemy's `mapped_column()` and `relationship()` return descriptor types (`MappedColumn[Any]`,
|
|
128
|
+
# `_RelationshipDeclared[Any]`) that ty cannot narrow to the declared `Mapped[...]` annotation.
|
|
129
|
+
# Every model attribute of the package trips this, 317 times, with nothing actionable to change:
|
|
130
|
+
# the annotation is the documented SQLAlchemy 2.0 style and mypy --strict accepts it. Re-enable
|
|
131
|
+
# once ty understands the SQLAlchemy declarative plugin.
|
|
132
|
+
unsound-assignment = "ignore"
|
|
133
|
+
unsound-return-statement = "ignore"
|
|
122
134
|
|
|
123
135
|
[tool.ty.src]
|
|
124
136
|
exclude = [
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line entry point for Alembic migrations, packaged with ``exobrain-database``.
|
|
3
|
+
|
|
4
|
+
The Alembic configuration file (``alembic.ini``) lives inside the installed
|
|
5
|
+
package, which makes it inconvenient to locate from a consuming project
|
|
6
|
+
(e.g. ``exobrain-server``) or from a container where the virtual environment
|
|
7
|
+
layout is not known in advance.
|
|
8
|
+
|
|
9
|
+
This module exposes a ``main()`` function, wired to the ``exobrain-db-migrate``
|
|
10
|
+
console script (see ``pyproject.toml``), which resolves ``alembic.ini``
|
|
11
|
+
relative to this module and delegates to Alembic's own command-line parser.
|
|
12
|
+
Every native Alembic command is therefore available unchanged, in particular
|
|
13
|
+
the ones needed for routine maintenance and diagnostics in a containerized
|
|
14
|
+
environment:
|
|
15
|
+
|
|
16
|
+
- ``exobrain-db-migrate current`` show the current revision(s)
|
|
17
|
+
- ``exobrain-db-migrate history`` list the migration history
|
|
18
|
+
- ``exobrain-db-migrate upgrade head`` apply pending migrations
|
|
19
|
+
- ``exobrain-db-migrate downgrade -1`` roll back one migration
|
|
20
|
+
- ``exobrain-db-migrate heads`` / ``show <rev>`` / ``stamp <rev>`` / ...
|
|
21
|
+
- ``exobrain-db-migrate -x schema=org_<id> current`` target a single org schema
|
|
22
|
+
|
|
23
|
+
Usage from anywhere, once ``exobrain-database`` is installed in the active
|
|
24
|
+
virtual environment::
|
|
25
|
+
|
|
26
|
+
exobrain-db-migrate upgrade head
|
|
27
|
+
exobrain-db-migrate -x schema=org_42 current
|
|
28
|
+
|
|
29
|
+
The database connection is read by ``env.py`` from the ``SQL_*`` environment
|
|
30
|
+
variables (``SQL_ENGINE``, ``SQL_HOST``, ``SQL_DATABASE``, ``SQL_USER``,
|
|
31
|
+
``SQL_PORT``, ``SQL_PASSWORD``), which must be set in the calling environment
|
|
32
|
+
(e.g.: injected into the container). Log output is written to ``stdout`` (see
|
|
33
|
+
the ``[handler_console]`` section of ``alembic.ini``), so it is captured by
|
|
34
|
+
container log collectors alongside the application's own logs.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
import os
|
|
38
|
+
import sys
|
|
39
|
+
from collections.abc import Sequence
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
|
|
42
|
+
from alembic.config import main as _alembic_main
|
|
43
|
+
|
|
44
|
+
HERE = Path(__file__).parent
|
|
45
|
+
DEFAULT_ALEMBIC_INI = HERE / "alembic.ini"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def main(argv: Sequence[str] | None = None) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Entry point for the ``exobrain-db-migrate`` console script.
|
|
51
|
+
|
|
52
|
+
Resolves the packaged ``alembic.ini`` and forwards all arguments to
|
|
53
|
+
Alembic's own command-line interface, so every native Alembic command
|
|
54
|
+
and option is supported unchanged.
|
|
55
|
+
|
|
56
|
+
An already-set ``ALEMBIC_CONFIG`` environment variable, or an explicit
|
|
57
|
+
``-c``/``--config`` argument, takes precedence over the packaged
|
|
58
|
+
default, so callers can still point to a different configuration file
|
|
59
|
+
if needed.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
argv: Command-line arguments to parse, excluding the program name.
|
|
63
|
+
Defaults to ``sys.argv[1:]``.
|
|
64
|
+
"""
|
|
65
|
+
# noinspection PyUnresolvedReferences
|
|
66
|
+
argv = argv if argv is not None else sys.argv[1:]
|
|
67
|
+
os.environ.setdefault("ALEMBIC_CONFIG", str(DEFAULT_ALEMBIC_INI))
|
|
68
|
+
_alembic_main(argv=argv, prog="exobrain-db-migrate")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__": # pragma: no cover
|
|
72
|
+
main()
|
|
@@ -6,6 +6,7 @@ from logging.config import fileConfig
|
|
|
6
6
|
from alembic import context
|
|
7
7
|
from alembic.runtime.environment import NameFilterType
|
|
8
8
|
from sqlalchemy import URL, Connection, Engine, Result, Table, column, create_engine, select, table
|
|
9
|
+
from sqlalchemy.pool import NullPool
|
|
9
10
|
from sqlalchemy.schema import CreateSchema
|
|
10
11
|
from sqlalchemy.sql import text
|
|
11
12
|
from sqlalchemy.sql.schema import SchemaItem
|
|
@@ -60,16 +61,16 @@ def has_autogenerate() -> bool:
|
|
|
60
61
|
"""
|
|
61
62
|
commands = _get_alembic_commands()
|
|
62
63
|
is_upgrade = len(commands) > 0 and callable(commands[0]) and commands[0].__name__ == "upgrade"
|
|
63
|
-
is_autogenerate = len(commands) > 2 and "autogenerate" in commands[2]
|
|
64
|
+
is_autogenerate = len(commands) > 2 and "autogenerate" in commands[2]
|
|
64
65
|
return is_upgrade or is_autogenerate
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
def is_public(
|
|
68
69
|
schema_item: SchemaItem,
|
|
69
|
-
name: str | None,
|
|
70
|
+
name: str | None,
|
|
70
71
|
type_: NameFilterType,
|
|
71
|
-
reflected: bool,
|
|
72
|
-
compare_to: SchemaItem | None,
|
|
72
|
+
reflected: bool,
|
|
73
|
+
compare_to: SchemaItem | None,
|
|
73
74
|
) -> bool:
|
|
74
75
|
if type_ == "table" and schema_item.info.get("skip_autogenerate"):
|
|
75
76
|
return False
|
|
@@ -89,7 +90,7 @@ def is_org(
|
|
|
89
90
|
schema_item: SchemaItem,
|
|
90
91
|
name: str | None,
|
|
91
92
|
type_: NameFilterType,
|
|
92
|
-
reflected: bool,
|
|
93
|
+
reflected: bool,
|
|
93
94
|
compare_to: SchemaItem | None,
|
|
94
95
|
) -> bool:
|
|
95
96
|
if type_ == "table" and schema_item.info.get("skip_autogenerate"):
|
|
@@ -111,8 +112,8 @@ def run_base_migrations_online(connection: Connection) -> None:
|
|
|
111
112
|
connection=connection,
|
|
112
113
|
target_metadata=base_metadata,
|
|
113
114
|
include_object=is_public,
|
|
114
|
-
upgrade_token="base_up",
|
|
115
|
-
downgrade_token="base_down",
|
|
115
|
+
upgrade_token="base_up",
|
|
116
|
+
downgrade_token="base_down",
|
|
116
117
|
compare_type=True,
|
|
117
118
|
)
|
|
118
119
|
|
|
@@ -144,8 +145,8 @@ def run_orgs_migrations_online(connection: Connection) -> None:
|
|
|
144
145
|
connection=connection,
|
|
145
146
|
target_metadata=base_metadata,
|
|
146
147
|
include_object=is_org,
|
|
147
|
-
upgrade_token="org_up",
|
|
148
|
-
downgrade_token="org_down",
|
|
148
|
+
upgrade_token="org_up",
|
|
149
|
+
downgrade_token="org_down",
|
|
149
150
|
compare_type=True,
|
|
150
151
|
)
|
|
151
152
|
|
|
@@ -181,20 +182,26 @@ def run_migrations_online() -> None:
|
|
|
181
182
|
port=sql_port,
|
|
182
183
|
database=sql_database,
|
|
183
184
|
)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
# A migration needs a single connection: ``NullPool`` closes it as soon as it is released,
|
|
186
|
+
# and ``dispose()`` frees the engine even when a migration fails. Without them, every Alembic
|
|
187
|
+
# command run in the same process (e.g. ``migration_manager.upgrade()`` for each organization)
|
|
188
|
+
# left a connection open, until PostgreSQL refused new clients (EXO-1800).
|
|
189
|
+
db_engine: Engine = create_engine(db_url, poolclass=NullPool)
|
|
190
|
+
try:
|
|
191
|
+
with db_engine.connect() as connection:
|
|
192
|
+
# If the first argument is a function, and it is a downgrade, we reverse the order of migrations
|
|
193
|
+
# to ensure that base migrations are applied before organization migrations.
|
|
194
|
+
commands = _get_alembic_commands()
|
|
195
|
+
is_downgrade = len(commands) > 0 and callable(commands[0]) and commands[0].__name__ == "downgrade"
|
|
196
|
+
if is_downgrade:
|
|
197
|
+
run_orgs_migrations_online(connection)
|
|
198
|
+
run_base_migrations_online(connection)
|
|
199
|
+
else:
|
|
200
|
+
run_base_migrations_online(connection)
|
|
201
|
+
run_orgs_migrations_online(connection)
|
|
202
|
+
connection.commit()
|
|
203
|
+
finally:
|
|
204
|
+
db_engine.dispose()
|
|
198
205
|
|
|
199
206
|
|
|
200
207
|
run_migrations_online()
|
|
@@ -106,4 +106,8 @@ def downgrade(org_id: UUID | int | str) -> None:
|
|
|
106
106
|
TypeError: If org_id is not a valid type (UUID, int, or numeric string).
|
|
107
107
|
"""
|
|
108
108
|
config = configure(org_id)
|
|
109
|
-
|
|
109
|
+
# "base", not "head": "head" is a no-op (the schema is already there), which silently skips
|
|
110
|
+
# every downgrade step -- e.g. it leaves running_risk/running_action/running_execution.status
|
|
111
|
+
# as their Postgres enum types instead of reverting them to TEXT, which then breaks servers
|
|
112
|
+
# rolled back to a pre-enum release (they query with a ::VARCHAR cast the enum type rejects).
|
|
113
|
+
command.downgrade(config, "base")
|