pyarchinit-mini 2.9.4__tar.gz → 2.9.5__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.
- {pyarchinit_mini-2.9.4/pyarchinit_mini.egg-info → pyarchinit_mini-2.9.5}/PKG-INFO +1 -1
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/__init__.py +1 -1
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/__init__.py +1 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/__main__.py +22 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/config.py +45 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/diff.py +19 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/engine.py +171 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/introspect.py +47 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/policy.py +13 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/rowmap.py +62 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/runner.py +33 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/state.py +44 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/sync_config.example.json +10 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/sync/transform.py +90 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/translations/en/LC_MESSAGES/messages.mo +0 -0
- pyarchinit_mini-2.9.5/pyarchinit_mini/translations/it/LC_MESSAGES/messages.mo +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5/pyarchinit_mini.egg-info}/PKG-INFO +1 -1
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/SOURCES.txt +24 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyproject.toml +2 -1
- pyarchinit_mini-2.9.5/tests/sync/conftest.py +31 -0
- pyarchinit_mini-2.9.5/tests/sync/test_config.py +33 -0
- pyarchinit_mini-2.9.5/tests/sync/test_diff.py +18 -0
- pyarchinit_mini-2.9.5/tests/sync/test_engine.py +144 -0
- pyarchinit_mini-2.9.5/tests/sync/test_introspect.py +16 -0
- pyarchinit_mini-2.9.5/tests/sync/test_policy.py +30 -0
- pyarchinit_mini-2.9.5/tests/sync/test_rowmap.py +24 -0
- pyarchinit_mini-2.9.5/tests/sync/test_runner.py +23 -0
- pyarchinit_mini-2.9.5/tests/sync/test_transform.py +51 -0
- pyarchinit_mini-2.9.5/tests/unit/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/CHANGELOG.md +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/MANIFEST.in +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/README.md +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/babel.cfg +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/data/pyarchinit_mini_sample.db +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/data/pyarchinit_tutorial.db +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/logo/logo_pyarchinit-mini.png +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/ai_matrix/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/ai_matrix/apply.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/ai_matrix/plan.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/ai_matrix/vision_extractor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/auth.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/dependencies.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/graphml.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/inventario.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/schemas.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/site.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/sync.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/api/us.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/export_import_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/extended_matrix_import.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/graphml_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/harris_import.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/harris_template.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/migrate.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/migrate_vocab.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/pyarchinit_import_export_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli/sync_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli_interface/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/cli_interface/cli_app.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/config/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/config/connection_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/config/em_node_config_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/config/em_node_types.yaml +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/concurrency_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/connection.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/database_creator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/add_file_path.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/add_i18n_columns.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/add_tipo_documento.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/change_us_area_to_text.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migration_scripts/change_us_area_to_text_simple.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/_2026_05_node_uuid_backfill.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/_2026_05_node_uuid_schema.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/_2026_05_period_table_schema.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/_2026_05_vocab_alignment.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/migrations/backup.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/postgres_installer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/schemas.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/database/utils.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/analytics_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/assets/logo.png +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/dialogs.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/excel_import_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/export_import_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/graphml_export_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/gui_app.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/harris_matrix_editor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/i18n.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/icons.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/inventario_dialog_extended.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/main_window.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/media_manager_advanced.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/postgres_installer_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/pottery_dialog_extended.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/pottery_panel.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/pyarchinit_import_export_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/thesaurus_dialog.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/desktop_gui/us_dialog_extended.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/dto/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/dto/inventario_dto.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/dto/site_dto.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/dto/us_dto.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/em_palette/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/em_palette/loader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/em_palette/styles.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/converter.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/dot_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/em_palette.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/graphml_builder.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/graphml_exporter.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/pure_networkx_exporter.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/svg_resources.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/templates/EM_palette.graphml +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/x11_colors.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_converter/yed_template.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/reader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/writer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/yed_importer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/yed_keys.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphml_io/yed_writer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/auto_regen.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/edge_registry.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/filesystem.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/graph_to_db.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/graphml_reader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/graphml_writer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/heriverse_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/ingest_plan.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/ingestor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/paradata_store.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/projector.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/rapporti_codec.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/s3d_projector.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/graphproj/s3d_to_cytoscape.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_matrix/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_matrix/enhanced_visualizer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_matrix/matrix_generator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_matrix/matrix_visualizer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_matrix/pyarchinit_visualizer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/compound_layout.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/harris_layout.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/period_sync_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/row_provider.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/harris_swimlane/swimlane_state.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/i18n/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/i18n/flask_babel_config.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/i18n/lang_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/i18n/locale_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/__main__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/blender_client.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/config.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/event_stream.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/graphml_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/http_server.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/period_filter.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/prompts/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/prompts/base_prompt.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/prompts/period_visualization_prompt.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/prompts/stratigraphic_model_prompt.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/prompts/us_description_prompt.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/proxy_generator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/base_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/graphml_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/periods_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/relationships_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/sites_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/resources/us_resource.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/server.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/base_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/batch_insert_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/build_3d_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/chatgpt_fetch_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/chatgpt_search_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/configure_em_nodes_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/create_database_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/create_harris_matrix_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/data_import_parser_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/data_management_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/database_manager_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/delete_data_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/export_harris_matrix_graphml_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/export_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/filter_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/generate_report_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/get_schema_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/import_excel_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/insert_data_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/manage_services_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/material_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/media_management_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/position_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/pyarchinit_sync_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/resolve_conflicts_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/service_management_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/thesaurus_management_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/update_data_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/upload_file_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/validate_relationship_format_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/validate_relationship_integrity_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/validate_stratigraphic_relationships_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/mcp_server/tools/validate_stratigraphy_tool.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/media_manager/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/media_manager/media_handler.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/ai_chat.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/app_setting.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/base.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/datazione.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/extended_matrix.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/harris_matrix.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/inventario_materiali.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/media.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/pottery.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/site.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/thesaurus.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/tma.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/us.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/models/user.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/pdf_generator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/pdf_generator_backup.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/pyarchinit_finds_template.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/pyarchinit_inventory_template.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/pdf_export/usm_implementation.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/s3d_integration/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/s3d_integration/model_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/s3d_integration/s3d_converter.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/auto_translate.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/configure_claude_desktop.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/create_admin_user.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/generate_test_3d_model.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/load_italian_as_main.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/load_sample_as_main.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/migrate_relationships.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/populate_sample_data.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/populate_simple_data.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/setup_auth.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/setup_user_env.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/test_cascade_delete.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/test_relationship_fix.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/update_sample_relationships.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/update_urls_and_versions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/scripts/verify_docs.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/ai_assistant_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/ai_chat_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/analytics_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/app_setting_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/backup_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/command_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/datazione_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/export_import_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/extended_matrix_excel_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/import_export_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/inventario_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/mcp_executor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/media_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/periodizzazione_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/pottery_dto.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/pottery_pdf_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/pottery_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/relationship_sync_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/search_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/site_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/thesaurus_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/tma_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/us_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/services/user_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/bundle_creator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/bundle_manifest.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/bundle_validator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/connectivity_monitor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/sync_orchestrator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/sync_queue.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/sync_state_machine.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/stratigraph/uuid_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/translations/en/LC_MESSAGES/messages.po +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/translations/it/LC_MESSAGES/messages.po +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/auth.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/relationship_validator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/stratigraphic_validator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/tma_label_generator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/utils/validators.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/i18n.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/loader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/provider.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/translations/vocab_en.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/translations/vocab_it.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/vocab/types.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/app.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/auth_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/em_node_config_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/excel_import_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/graph_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/harris_creator_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/matrix_import_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/matrix_tools_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/paradata_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/paradata_ui_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/pottery_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/pyarchinit_import_export_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/s3d_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/socketio_events.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/css/style.css +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/images/favicon.ico +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/images/logo.png +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/images/no-image.png +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/images/pyarchinit-mini-logo.png +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/OrbitControls.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/harris_creator_editor.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/stratigraphic_layout.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/three-d-viewer.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/three.min.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/js/universal_search.js +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.bin +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.gltf +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.mtl +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.obj +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/3d_builder/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/3d_viewer/viewer.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/backups.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/database.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/database_connect.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/database_info.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/database_upload.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/admin/settings_ai.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/ai/assistant.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/analytics/dashboard.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/auth/login.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/auth/users.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/base.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/blender_viewer.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/components/language_switcher.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/dashboard.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/datazioni/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/docs/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/em_node_config/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/excel_import/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/export/export_import.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/graph_import_preview.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/graph_import_result.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_creator/editor.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_creator/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/graphml_export.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/large_graph_message.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/stratigraph_viewer.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/view.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/view_graphviz.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/harris_matrix/viewer_3d_integrated.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/inventario/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/inventario/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/matrix_import/preview.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/matrix_import/rejected.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/matrix_import/upload.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/matrix_tools/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/media/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/media/upload.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/messaging/contacts.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/operators/directory.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/paradata/edit.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/paradata/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/paradata/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pdf/pottery_sheet.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/periodizzazione/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/periodizzazione/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/periodizzazione/periods.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pottery/detail.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pottery/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pottery/import_form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pottery/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/pyarchinit_import_export/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/search/results.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/sites/detail.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/sites/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/sites/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/sites/map.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/stats/targeted.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/thesaurus/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/tma/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/tma/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/us/form.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/us/list.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/validation/report.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/yed_import/index.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/yed_import/preview.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/templates/yed_import/result.html +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/test_prova_extended_matrix.graphml +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/three_d_builder_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.graphml +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/vocab_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_heriverse.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.graphml +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini/web_interface/yed_import_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/dependency_links.txt +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/entry_points.txt +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/not-zip-safe +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/requires.txt +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/pyarchinit_mini.egg-info/top_level.txt +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/requirements.txt +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/setup.cfg +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/setup.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/conftest.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/e2e/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/e2e/test_web_vocab_full_flow.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/fixtures/_generate_baseline_graphml.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/fixtures/_generate_harris_swimlane_synthetic.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/fixtures/_generate_synthetic_db.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/fixtures/_generate_yed_test_files.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/fixtures/build_legacy_with_pottery.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_adarte_regression.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_admin_ai_settings_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_admin_backup_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_api_export_graphml.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_api_export_heriverse.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_api_import_graphml.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_api_import_json.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_api_load_site.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_auto_regen_on_save.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_feature_flag_pipelines.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_full_sync_flow.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_graph_import_flow.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_graph_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_matrix_post_cutover.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_matrix_visual_parity.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_swimlane_routes_create_row.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_swimlane_routes_load.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_swimlane_routes_save.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_harris_swimlane_routes_session_missing.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_lang_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_matrix_import_apply_route.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_matrix_import_rejected_route.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_matrix_import_site_widget.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_matrix_import_upload_route.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_migrate_vocab_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_paradata_routes_authors.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_paradata_routes_other_types.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_paradata_ui.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_completion.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_excel_roundtrip.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_filters_id_number_anno.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_legacy_upgrade.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_list_media_thumbs.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_pottery_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_roundtrip.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_roundtrip_extmatrix.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_spec2_coverage_gaps.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_swimlane_group_by.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_vocab_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_yed_export_route.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_yed_import_routes.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/integration/test_yed_writer_parity.py +0 -0
- {pyarchinit_mini-2.9.4/tests/unit → pyarchinit_mini-2.9.5/tests/sync}/__init__.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_ai_matrix_apply.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_ai_matrix_extractor_parse.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_ai_matrix_extractor_providers.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_ai_matrix_plan_serialization.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_app_setting_model.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_app_setting_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_auto_regen.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_backup_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_bundle.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_concurrency_columns.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_concurrency_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_connectivity_monitor.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_database_utils.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_deprecated_writers_shim.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_em_palette_vocab_backed.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graph_to_db.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphml_io_reader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphml_io_writer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_edge_registry.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_filesystem.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_ingestor_apply.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_ingestor_preview.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_graphproj_projector.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_layout.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_compound_layout.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_period_sync.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_row_provider.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_state_load.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_harris_swimlane_state_save.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_heriverse_parser.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_ingest_plan.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_inventario_schema.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_migrations_backup.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_migrations_idempotent.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_optimistic_locking.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_palette_loader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_palette_styles.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_paradata_store_authors.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_paradata_store_basic.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_paradata_store_other_types.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_pottery_dto.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_pottery_model.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_pottery_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_rapporti_codec.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_rapporti_codec_display.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_s3d_converter_vocab_backed.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_s3d_projector.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_s3d_to_cytoscape.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_site_service.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_sync_api.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_sync_cli.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_sync_orchestrator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_sync_queue.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_sync_state_machine.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_us_dto_unita_tipo_validator.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_us_schema.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_uuid_manager.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_bootstrap_failures.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_exceptions.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_i18n.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_loader.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_provider.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_vocab_types.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_yed_importer_parse.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_yed_importer_plan.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_yed_writer.py +0 -0
- {pyarchinit_mini-2.9.4 → pyarchinit_mini-2.9.5}/tests/unit/test_yed_writer_extended_matrix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyarchinit-mini
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.5
|
|
4
4
|
Summary: Lightweight archaeological data management system with REST API, Web UI, Desktop GUI, CLI, multi-user authentication, real-time collaboration, analytics dashboard, PyArchInit import/export, Heriverse/ATON export integration, and 3D CRUD viewer
|
|
5
5
|
Home-page: https://github.com/enzococca/pyarchinit-mini
|
|
6
6
|
Author: PyArchInit Team
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""One-way sync engine: classic pyarchinit -> pyarchinit_v2 (mini)."""
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import argparse, logging, sys
|
|
2
|
+
from .config import load_config
|
|
3
|
+
from .runner import run
|
|
4
|
+
|
|
5
|
+
def main(argv=None):
|
|
6
|
+
p = argparse.ArgumentParser(prog="python -m pyarchinit_mini.sync",
|
|
7
|
+
description="Sync classic pyarchinit -> pyarchinit_v2")
|
|
8
|
+
p.add_argument("--config", default=None)
|
|
9
|
+
p.add_argument("--apply", action="store_true", help="write changes (default: dry-run)")
|
|
10
|
+
p.add_argument("--tables", default=None, help="comma-separated subset")
|
|
11
|
+
p.add_argument("--log", default=None, help="log file (default: stderr)")
|
|
12
|
+
args = p.parse_args(argv)
|
|
13
|
+
logging.basicConfig(level=logging.INFO, filename=args.log,
|
|
14
|
+
format="%(asctime)s %(levelname)s %(message)s")
|
|
15
|
+
cfg = load_config(args.config)
|
|
16
|
+
tables = [t.strip() for t in args.tables.split(",")] if args.tables else None
|
|
17
|
+
results = run(cfg, tables=tables, dry_run=not args.apply)
|
|
18
|
+
errors = [r for r in results if r.error]
|
|
19
|
+
sys.exit(1 if errors else 0)
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
main()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import json, os
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import Mapping
|
|
4
|
+
|
|
5
|
+
DEFAULT_PRESERVE = frozenset({
|
|
6
|
+
"order_layer", "cont_per", "entity_uuid", "node_uuid", "version_number",
|
|
7
|
+
"created_at", "updated_at", "last_modified_timestamp", "last_modified_by",
|
|
8
|
+
"editing_since", "editing_by", "audit_trail", "sync_status",
|
|
9
|
+
})
|
|
10
|
+
DEFAULT_EXCLUDE = frozenset({"spatial_ref_sys", "raster_columns", "raster_overviews"})
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class Config:
|
|
14
|
+
source_dsn: str
|
|
15
|
+
target_dsn: str
|
|
16
|
+
size_threshold_keyset: int = 200_000
|
|
17
|
+
exclude_tables: frozenset[str] = DEFAULT_EXCLUDE
|
|
18
|
+
preserve_columns_global: frozenset[str] = DEFAULT_PRESERVE
|
|
19
|
+
overrides: dict[str, dict] = field(default_factory=dict)
|
|
20
|
+
weekly_full_refresh: bool = True
|
|
21
|
+
delete_enabled: bool = True
|
|
22
|
+
delete_on_empty_source: bool = False
|
|
23
|
+
collision_id_base: int = 1_000_000_000
|
|
24
|
+
|
|
25
|
+
def load_config(path: str | None = None, env: Mapping[str, str] = os.environ) -> Config:
|
|
26
|
+
raw = {}
|
|
27
|
+
if path:
|
|
28
|
+
with open(path, encoding="utf-8") as fh:
|
|
29
|
+
raw = json.load(fh)
|
|
30
|
+
src_env = raw.get("source_dsn_env", "PYARCHINIT_CLASSIC_DSN")
|
|
31
|
+
tgt_env = raw.get("target_dsn_env", "DATABASE_URL")
|
|
32
|
+
source_dsn = env[src_env] # KeyError if missing — intentional
|
|
33
|
+
target_dsn = env[tgt_env]
|
|
34
|
+
preserve = DEFAULT_PRESERVE | frozenset(raw.get("preserve_columns_global", []))
|
|
35
|
+
exclude = DEFAULT_EXCLUDE | frozenset(raw.get("exclude_tables", []))
|
|
36
|
+
return Config(
|
|
37
|
+
source_dsn=source_dsn, target_dsn=target_dsn,
|
|
38
|
+
size_threshold_keyset=int(raw.get("size_threshold_keyset", 200_000)),
|
|
39
|
+
exclude_tables=exclude, preserve_columns_global=preserve,
|
|
40
|
+
overrides=raw.get("overrides", {}),
|
|
41
|
+
weekly_full_refresh=bool(raw.get("weekly_full_refresh", True)),
|
|
42
|
+
delete_enabled=bool(raw.get("delete_enabled", True)),
|
|
43
|
+
delete_on_empty_source=bool(raw.get("delete_on_empty_source", False)),
|
|
44
|
+
collision_id_base=int(raw.get("collision_id_base", 1_000_000_000)),
|
|
45
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
@dataclass
|
|
4
|
+
class Diff:
|
|
5
|
+
inserts: list
|
|
6
|
+
updates: list
|
|
7
|
+
deletes: list
|
|
8
|
+
|
|
9
|
+
def diff_by_hash(source: dict[tuple, str], target: dict[tuple, str]) -> Diff:
|
|
10
|
+
src_keys, tgt_keys = set(source), set(target)
|
|
11
|
+
inserts = sorted(src_keys - tgt_keys)
|
|
12
|
+
deletes = sorted(tgt_keys - src_keys)
|
|
13
|
+
updates = sorted(k for k in (src_keys & tgt_keys) if source[k] != target[k])
|
|
14
|
+
return Diff(inserts=inserts, updates=updates, deletes=deletes)
|
|
15
|
+
|
|
16
|
+
def diff_by_keyset(source_keys: set[tuple], target_keys: set[tuple]) -> Diff:
|
|
17
|
+
return Diff(inserts=sorted(source_keys - target_keys),
|
|
18
|
+
updates=[],
|
|
19
|
+
deletes=sorted(target_keys - source_keys))
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from psycopg2.extensions import connection
|
|
4
|
+
from . import introspect as I, transform as T, state as S, rowmap as M
|
|
5
|
+
from .diff import diff_by_hash
|
|
6
|
+
from .policy import select_mode, is_gated, preserve_set_for_table, common_data_columns
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class TableResult:
|
|
10
|
+
table: str; mode: str; inserted: int; updated: int; deleted: int
|
|
11
|
+
skipped: bool; error: str | None
|
|
12
|
+
|
|
13
|
+
_FILL_DEFAULTS = {
|
|
14
|
+
"created_at": "now()", "updated_at": "now()", "version_number": "1",
|
|
15
|
+
"entity_uuid": "gen_random_uuid()::text", "node_uuid": "gen_random_uuid()::text",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
def _source_hash(src_conn, table, pk, common, src_types, tgt_types, geom):
|
|
19
|
+
hcols = [c for c in common if c != pk] # pk excluded; identity is the map, not the hash
|
|
20
|
+
cur = src_conn.cursor()
|
|
21
|
+
cur.execute(T.build_pk_hash_select_coerced(table, [pk], hcols, src_types, tgt_types, geom))
|
|
22
|
+
return {str(r[0]): r[1] for r in cur.fetchall()}
|
|
23
|
+
|
|
24
|
+
def _target_hash(tgt_conn, table, pk, common, tgt_types):
|
|
25
|
+
hcols = [c for c in common if c != pk]
|
|
26
|
+
cur = tgt_conn.cursor()
|
|
27
|
+
cur.execute(f'select "{pk}"::text, {T.plain_row_hash_sql(hcols, tgt_types)} from public."{table}"')
|
|
28
|
+
return {r[0]: r[1] for r in cur.fetchall()}
|
|
29
|
+
|
|
30
|
+
def _fetch_source_row(src_conn, table, common, pk, v1_pk):
|
|
31
|
+
cur = src_conn.cursor()
|
|
32
|
+
cols = ", ".join(f'"{c}"' for c in common)
|
|
33
|
+
cur.execute(f'select {cols} from public."{table}" where "{pk}"::text=%s', (v1_pk,))
|
|
34
|
+
return cur.fetchone()
|
|
35
|
+
|
|
36
|
+
def _value_exprs(common, src_types, tgt_types, geom):
|
|
37
|
+
out = []
|
|
38
|
+
for c in common:
|
|
39
|
+
tgt_t = "geometry" if c in geom else tgt_types[c][0]
|
|
40
|
+
out.append(T.cast_expr(src_types[c][0], tgt_t, tgt_types[c][1], ph=f"%({c})s"))
|
|
41
|
+
return out
|
|
42
|
+
|
|
43
|
+
def _insert_one(tgt_conn, table, common, pk, row, v2_pk, src_types, tgt_types, geom):
|
|
44
|
+
# row is aligned to `common`; force the pk column to the chosen v2_pk
|
|
45
|
+
exprs = _value_exprs(common, src_types, tgt_types, geom)
|
|
46
|
+
fill = {c: v for c, v in _FILL_DEFAULTS.items() if c in tgt_types and c not in common}
|
|
47
|
+
cols = common + list(fill.keys())
|
|
48
|
+
col_sql = ", ".join(f'"{c}"' for c in cols)
|
|
49
|
+
val_sql = ", ".join(exprs + list(fill.values()))
|
|
50
|
+
params = {c: row[i] for i, c in enumerate(common)}
|
|
51
|
+
params[pk] = v2_pk # override pk value with the chosen v2_pk
|
|
52
|
+
tgt_conn.cursor().execute(
|
|
53
|
+
f'INSERT INTO public."{table}" ({col_sql}) VALUES ({val_sql})', params)
|
|
54
|
+
|
|
55
|
+
def _update_one(tgt_conn, table, common, pk, row, v2_pk, src_types, tgt_types, geom):
|
|
56
|
+
set_cols = [c for c in common if c != pk] # never update the pk
|
|
57
|
+
exprs = _value_exprs(set_cols, src_types, tgt_types, geom)
|
|
58
|
+
assigns = ", ".join(f'"{c}" = {e}' for c, e in zip(set_cols, exprs))
|
|
59
|
+
params = {c: row[common.index(c)] for c in set_cols}
|
|
60
|
+
params["__v2pk"] = v2_pk
|
|
61
|
+
tgt_conn.cursor().execute(
|
|
62
|
+
f'UPDATE public."{table}" SET {assigns} WHERE "{pk}"::text = %(__v2pk)s', params)
|
|
63
|
+
|
|
64
|
+
def _delete_one(tgt_conn, table, pk, v2_pk):
|
|
65
|
+
tgt_conn.cursor().execute(f'delete from public."{table}" where "{pk}"::text=%s', (v2_pk,))
|
|
66
|
+
|
|
67
|
+
def _alloc_v2_pk(v1_pk, v2pks, state):
|
|
68
|
+
if v1_pk not in v2pks:
|
|
69
|
+
return v1_pk
|
|
70
|
+
nxt = state["next_high"]
|
|
71
|
+
while str(nxt) in v2pks:
|
|
72
|
+
nxt += 1
|
|
73
|
+
state["next_high"] = nxt + 1
|
|
74
|
+
return str(nxt)
|
|
75
|
+
|
|
76
|
+
def sync_table(src_conn, tgt_conn, table, cfg, dry_run=True) -> TableResult:
|
|
77
|
+
mode = "unknown"; ins = upd = dele = 0
|
|
78
|
+
try:
|
|
79
|
+
M.ensure_map_table(tgt_conn); S.ensure_state_table(tgt_conn)
|
|
80
|
+
pk_cols = I.primary_key(src_conn, table)
|
|
81
|
+
single_pk = pk_cols[0] if len(pk_cols) == 1 else None
|
|
82
|
+
mode = select_mode(single_pk is not None)
|
|
83
|
+
rc = I.row_count(src_conn, table)
|
|
84
|
+
src_types = I.column_types(src_conn, table)
|
|
85
|
+
tgt_types = I.column_types(tgt_conn, table)
|
|
86
|
+
geom = I.geometry_columns(tgt_conn, table)
|
|
87
|
+
preserve = preserve_set_for_table(cfg.preserve_columns_global,
|
|
88
|
+
set(src_types), set(tgt_types), [])
|
|
89
|
+
common = common_data_columns(set(src_types), set(tgt_types), preserve)
|
|
90
|
+
if mode == "additive":
|
|
91
|
+
src_hexpr = T.coerced_row_hash_sql(common, src_types, tgt_types, geom)
|
|
92
|
+
tgt_hexpr = T.plain_row_hash_sql(common, tgt_types)
|
|
93
|
+
scur = src_conn.cursor()
|
|
94
|
+
scur.execute(f'select {src_hexpr}, {", ".join(chr(34)+c+chr(34) for c in common)} '
|
|
95
|
+
f'from public."{table}"')
|
|
96
|
+
srows = scur.fetchall()
|
|
97
|
+
tcur = tgt_conn.cursor()
|
|
98
|
+
tcur.execute(f'select {tgt_hexpr} from public."{table}"')
|
|
99
|
+
seen = {r[0] for r in tcur.fetchall()}
|
|
100
|
+
exprs = _value_exprs(common, src_types, tgt_types, geom)
|
|
101
|
+
col_sql = ", ".join(f'"{c}"' for c in common)
|
|
102
|
+
sql = f'INSERT INTO public."{table}" ({col_sql}) VALUES ({", ".join(exprs)})'
|
|
103
|
+
icur = tgt_conn.cursor()
|
|
104
|
+
for r in srows:
|
|
105
|
+
h = r[0]
|
|
106
|
+
if h in seen:
|
|
107
|
+
continue
|
|
108
|
+
seen.add(h)
|
|
109
|
+
row = r[1:]
|
|
110
|
+
params = {c: row[i] for i, c in enumerate(common)}
|
|
111
|
+
icur.execute(sql, params)
|
|
112
|
+
ins += 1
|
|
113
|
+
if dry_run:
|
|
114
|
+
tgt_conn.rollback()
|
|
115
|
+
else:
|
|
116
|
+
S.record_result(tgt_conn, table, I.signature(src_conn, table, pk_cols),
|
|
117
|
+
mode, ins, 0, 0, None)
|
|
118
|
+
tgt_conn.commit()
|
|
119
|
+
return TableResult(table, mode, ins, 0, 0, False, None)
|
|
120
|
+
if is_gated(rc, cfg.size_threshold_keyset):
|
|
121
|
+
if I.signature(src_conn, table, pk_cols) == S.get_signature(tgt_conn, table):
|
|
122
|
+
tgt_conn.rollback()
|
|
123
|
+
return TableResult(table, mode, 0, 0, 0, True, None)
|
|
124
|
+
if M.map_count(tgt_conn, table) == 0:
|
|
125
|
+
M.bootstrap_table(tgt_conn, src_conn, table, single_pk)
|
|
126
|
+
mp = M.load_map(tgt_conn, table) # {v1_pk: v2_pk}
|
|
127
|
+
src = _source_hash(src_conn, table, single_pk, common, src_types, tgt_types, geom)
|
|
128
|
+
tgt_h = _target_hash(tgt_conn, table, single_pk, common, tgt_types) # {v2_pk: hash}
|
|
129
|
+
target = {v1: tgt_h.get(v2) for v1, v2 in mp.items()} # {v1_pk: hash-of-its-v2-row}
|
|
130
|
+
d = diff_by_hash(src, target)
|
|
131
|
+
v2pks = M.v2_pk_set(tgt_conn, table, single_pk)
|
|
132
|
+
nums = [int(x) for x in v2pks if re.fullmatch(r"-?\d+", x)]
|
|
133
|
+
state = {"next_high": max([cfg.collision_id_base] + [n + 1 for n in nums])}
|
|
134
|
+
if cfg.delete_enabled and (rc > 0 or cfg.delete_on_empty_source):
|
|
135
|
+
for v1k in d.deletes:
|
|
136
|
+
_delete_one(tgt_conn, table, single_pk, mp[v1k]); M.delete_map(tgt_conn, table, v1k); dele += 1
|
|
137
|
+
for v1k in d.inserts:
|
|
138
|
+
row = _fetch_source_row(src_conn, table, common, single_pk, v1k)
|
|
139
|
+
if row is None:
|
|
140
|
+
continue
|
|
141
|
+
v2k = _alloc_v2_pk(v1k, v2pks, state)
|
|
142
|
+
_insert_one(tgt_conn, table, common, single_pk, row, v2k, src_types, tgt_types, geom)
|
|
143
|
+
M.upsert_map(tgt_conn, table, v1k, v2k); v2pks.add(v2k); ins += 1
|
|
144
|
+
for v1k in d.updates:
|
|
145
|
+
v2k = mp[v1k]
|
|
146
|
+
row = _fetch_source_row(src_conn, table, common, single_pk, v1k)
|
|
147
|
+
if row is None:
|
|
148
|
+
continue
|
|
149
|
+
if v2k in v2pks:
|
|
150
|
+
_update_one(tgt_conn, table, common, single_pk, row, v2k, src_types, tgt_types, geom)
|
|
151
|
+
else: # mapped row deleted in v2 -> re-insert
|
|
152
|
+
v2k = _alloc_v2_pk(v1k, v2pks, state)
|
|
153
|
+
_insert_one(tgt_conn, table, common, single_pk, row, v2k, src_types, tgt_types, geom)
|
|
154
|
+
M.upsert_map(tgt_conn, table, v1k, v2k); v2pks.add(v2k)
|
|
155
|
+
upd += 1
|
|
156
|
+
if dry_run:
|
|
157
|
+
tgt_conn.rollback()
|
|
158
|
+
else:
|
|
159
|
+
S.record_result(tgt_conn, table, I.signature(src_conn, table, pk_cols),
|
|
160
|
+
mode, ins, upd, dele, None)
|
|
161
|
+
tgt_conn.commit()
|
|
162
|
+
return TableResult(table, mode, ins, upd, dele, False, None)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
tgt_conn.rollback()
|
|
165
|
+
msg = str(e).splitlines()[0]
|
|
166
|
+
try:
|
|
167
|
+
S.ensure_state_table(tgt_conn)
|
|
168
|
+
S.record_result(tgt_conn, table, "", mode, 0, 0, 0, msg); tgt_conn.commit()
|
|
169
|
+
except Exception:
|
|
170
|
+
tgt_conn.rollback()
|
|
171
|
+
return TableResult(table, mode, 0, 0, 0, False, msg)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from psycopg2.extensions import connection
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def base_tables(conn: connection) -> set[str]:
|
|
5
|
+
cur = conn.cursor()
|
|
6
|
+
cur.execute("select table_name from information_schema.tables "
|
|
7
|
+
"where table_schema='public' and table_type='BASE TABLE'")
|
|
8
|
+
return {r[0] for r in cur.fetchall()}
|
|
9
|
+
|
|
10
|
+
def column_types(conn: connection, table: str) -> dict[str, tuple[str, int | None]]:
|
|
11
|
+
cur = conn.cursor()
|
|
12
|
+
cur.execute("select column_name, data_type, character_maximum_length "
|
|
13
|
+
"from information_schema.columns where table_schema='public' and table_name=%s",
|
|
14
|
+
(table,))
|
|
15
|
+
return {r[0]: (r[1], r[2]) for r in cur.fetchall()}
|
|
16
|
+
|
|
17
|
+
def primary_key(conn: connection, table: str) -> list[str]:
|
|
18
|
+
cur = conn.cursor()
|
|
19
|
+
cur.execute("""select a.attname from pg_index i
|
|
20
|
+
join pg_class c on c.oid=i.indrelid
|
|
21
|
+
join pg_namespace n on n.oid=c.relnamespace
|
|
22
|
+
join pg_attribute a on a.attrelid=c.oid and a.attnum=any(i.indkey)
|
|
23
|
+
where n.nspname='public' and c.relname=%s and i.indisprimary
|
|
24
|
+
order by a.attnum""", (table,))
|
|
25
|
+
return [r[0] for r in cur.fetchall()]
|
|
26
|
+
|
|
27
|
+
def geometry_columns(conn: connection, table: str) -> set[str]:
|
|
28
|
+
cur = conn.cursor()
|
|
29
|
+
cur.execute("select column_name from information_schema.columns "
|
|
30
|
+
"where table_schema='public' and table_name=%s "
|
|
31
|
+
"and udt_name in ('geometry','geography')", (table,))
|
|
32
|
+
return {r[0] for r in cur.fetchall()}
|
|
33
|
+
|
|
34
|
+
def row_count(conn: connection, table: str) -> int:
|
|
35
|
+
cur = conn.cursor()
|
|
36
|
+
cur.execute(f'select count(*) from public."{table}"')
|
|
37
|
+
return cur.fetchone()[0]
|
|
38
|
+
|
|
39
|
+
def signature(conn: connection, table: str, pk: list[str]) -> str:
|
|
40
|
+
cur = conn.cursor()
|
|
41
|
+
cur.execute(f'select count(*) from public."{table}"')
|
|
42
|
+
cnt = cur.fetchone()[0]
|
|
43
|
+
maxpk = ""
|
|
44
|
+
if pk:
|
|
45
|
+
cur.execute(f'select max("{pk[0]}") from public."{table}"')
|
|
46
|
+
maxpk = str(cur.fetchone()[0])
|
|
47
|
+
return f"{cnt}:{maxpk}"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
def select_mode(has_single_pk: bool) -> str:
|
|
2
|
+
return "mapped" if has_single_pk else "additive"
|
|
3
|
+
|
|
4
|
+
def is_gated(rowcount: int, threshold: int) -> bool:
|
|
5
|
+
return rowcount > threshold
|
|
6
|
+
|
|
7
|
+
def preserve_set_for_table(global_preserve: frozenset[str], src_cols: set[str], tgt_cols: set[str], extra: list[str]) -> set[str]:
|
|
8
|
+
target_only = set(tgt_cols) - set(src_cols)
|
|
9
|
+
en_cols = {c for c in tgt_cols if c.endswith("_en")}
|
|
10
|
+
return set(global_preserve) | target_only | en_cols | set(extra or [])
|
|
11
|
+
|
|
12
|
+
def common_data_columns(src_cols: set[str], tgt_cols: set[str], preserve: set[str]) -> list[str]:
|
|
13
|
+
return sorted((set(src_cols) & set(tgt_cols)) - set(preserve))
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from psycopg2.extensions import connection
|
|
2
|
+
from psycopg2.extras import execute_values
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def ensure_map_table(conn: connection) -> None:
|
|
6
|
+
conn.cursor().execute("""
|
|
7
|
+
CREATE TABLE IF NOT EXISTS public.sync_row_map (
|
|
8
|
+
table_name text NOT NULL,
|
|
9
|
+
v1_pk text NOT NULL,
|
|
10
|
+
v2_pk text NOT NULL,
|
|
11
|
+
last_run_at timestamptz DEFAULT now(),
|
|
12
|
+
PRIMARY KEY (table_name, v1_pk),
|
|
13
|
+
UNIQUE (table_name, v2_pk)
|
|
14
|
+
)""")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def map_count(conn: connection, table: str) -> int:
|
|
18
|
+
cur = conn.cursor()
|
|
19
|
+
cur.execute("select count(*) from public.sync_row_map where table_name=%s", (table,))
|
|
20
|
+
return cur.fetchone()[0]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def load_map(conn: connection, table: str) -> dict[str, str]:
|
|
24
|
+
cur = conn.cursor()
|
|
25
|
+
cur.execute("select v1_pk, v2_pk from public.sync_row_map where table_name=%s", (table,))
|
|
26
|
+
return {r[0]: r[1] for r in cur.fetchall()}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def v2_pk_set(conn: connection, table: str, pk: str) -> set[str]:
|
|
30
|
+
cur = conn.cursor()
|
|
31
|
+
cur.execute(f'select "{pk}"::text from public."{table}"')
|
|
32
|
+
return {r[0] for r in cur.fetchall()}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def bootstrap_table(tgt_conn: connection, src_conn: connection, table: str, pk: str) -> int:
|
|
36
|
+
if map_count(tgt_conn, table) > 0: # only bootstrap an empty map
|
|
37
|
+
return 0
|
|
38
|
+
scur = src_conn.cursor()
|
|
39
|
+
scur.execute(f'select "{pk}"::text from public."{table}"')
|
|
40
|
+
v1 = {r[0] for r in scur.fetchall()}
|
|
41
|
+
v2 = v2_pk_set(tgt_conn, table, pk)
|
|
42
|
+
overlap = sorted(v1 & v2)
|
|
43
|
+
if not overlap:
|
|
44
|
+
return 0
|
|
45
|
+
tcur = tgt_conn.cursor()
|
|
46
|
+
execute_values(tcur,
|
|
47
|
+
"INSERT INTO public.sync_row_map (table_name, v1_pk, v2_pk) VALUES %s "
|
|
48
|
+
"ON CONFLICT (table_name, v1_pk) DO NOTHING",
|
|
49
|
+
[(table, k, k) for k in overlap])
|
|
50
|
+
return len(overlap)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def upsert_map(conn: connection, table: str, v1_pk: str, v2_pk: str) -> None:
|
|
54
|
+
conn.cursor().execute(
|
|
55
|
+
"INSERT INTO public.sync_row_map (table_name, v1_pk, v2_pk) VALUES (%s,%s,%s) "
|
|
56
|
+
"ON CONFLICT (table_name, v1_pk) DO UPDATE SET v2_pk=EXCLUDED.v2_pk, last_run_at=now()",
|
|
57
|
+
(table, v1_pk, v2_pk))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def delete_map(conn: connection, table: str, v1_pk: str) -> None:
|
|
61
|
+
conn.cursor().execute(
|
|
62
|
+
"delete from public.sync_row_map where table_name=%s and v1_pk=%s", (table, v1_pk))
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import logging, psycopg2
|
|
2
|
+
from psycopg2.extensions import connection
|
|
3
|
+
from . import introspect as I
|
|
4
|
+
from .config import Config
|
|
5
|
+
from .engine import sync_table, TableResult
|
|
6
|
+
|
|
7
|
+
def discover_tables(src_conn: connection, tgt_conn: connection, cfg: Config) -> list[str]:
|
|
8
|
+
mirrored = I.base_tables(src_conn) & I.base_tables(tgt_conn)
|
|
9
|
+
return sorted(mirrored - set(cfg.exclude_tables))
|
|
10
|
+
|
|
11
|
+
def run(cfg: Config, tables: list[str] | None = None, dry_run: bool = True, logger=None, _conns: tuple | None = None) -> list[TableResult]:
|
|
12
|
+
logger = logger or logging.getLogger("sync")
|
|
13
|
+
src, tgt = _conns or (psycopg2.connect(cfg.source_dsn), psycopg2.connect(cfg.target_dsn))
|
|
14
|
+
src.autocommit = True # source: read-only
|
|
15
|
+
owns = _conns is None
|
|
16
|
+
try:
|
|
17
|
+
names = tables if tables else discover_tables(src, tgt, cfg)
|
|
18
|
+
results = []
|
|
19
|
+
ti = tu = td = 0
|
|
20
|
+
for name in names:
|
|
21
|
+
r = sync_table(src, tgt, name, cfg, dry_run=dry_run)
|
|
22
|
+
results.append(r)
|
|
23
|
+
ti += r.inserted; tu += r.updated; td += r.deleted
|
|
24
|
+
tag = "DRY" if dry_run else "APPLY"
|
|
25
|
+
state = "SKIP" if r.skipped else ("ERR:" + r.error if r.error else "ok")
|
|
26
|
+
logger.info("[%s] %-40s mode=%-7s +%d ~%d -%d %s",
|
|
27
|
+
tag, name, r.mode, r.inserted, r.updated, r.deleted, state)
|
|
28
|
+
logger.info("[%s] TOTAL tables=%d +%d ~%d -%d",
|
|
29
|
+
"DRY" if dry_run else "APPLY", len(results), ti, tu, td)
|
|
30
|
+
return results
|
|
31
|
+
finally:
|
|
32
|
+
if owns:
|
|
33
|
+
src.close(); tgt.close()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""sync_state tracking table — records last sync result per table."""
|
|
2
|
+
from psycopg2.extensions import connection
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def ensure_state_table(conn: connection) -> None:
|
|
6
|
+
conn.cursor().execute("""
|
|
7
|
+
CREATE TABLE IF NOT EXISTS public.sync_state (
|
|
8
|
+
table_name text PRIMARY KEY,
|
|
9
|
+
last_signature text,
|
|
10
|
+
last_run_at timestamptz DEFAULT now(),
|
|
11
|
+
last_mode text,
|
|
12
|
+
rows_inserted int DEFAULT 0,
|
|
13
|
+
rows_updated int DEFAULT 0,
|
|
14
|
+
rows_deleted int DEFAULT 0,
|
|
15
|
+
error text
|
|
16
|
+
)""")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_signature(conn: connection, table: str) -> str | None:
|
|
20
|
+
cur = conn.cursor()
|
|
21
|
+
cur.execute("select last_signature from public.sync_state where table_name=%s", (table,))
|
|
22
|
+
row = cur.fetchone()
|
|
23
|
+
return row[0] if row else None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def record_result(
|
|
27
|
+
conn: connection,
|
|
28
|
+
table: str,
|
|
29
|
+
signature: str,
|
|
30
|
+
mode: str,
|
|
31
|
+
inserted: int,
|
|
32
|
+
updated: int,
|
|
33
|
+
deleted: int,
|
|
34
|
+
error: str | None,
|
|
35
|
+
) -> None:
|
|
36
|
+
conn.cursor().execute("""
|
|
37
|
+
INSERT INTO public.sync_state
|
|
38
|
+
(table_name, last_signature, last_run_at, last_mode, rows_inserted, rows_updated, rows_deleted, error)
|
|
39
|
+
VALUES (%s,%s,now(),%s,%s,%s,%s,%s)
|
|
40
|
+
ON CONFLICT (table_name) DO UPDATE SET
|
|
41
|
+
last_signature=EXCLUDED.last_signature, last_run_at=now(), last_mode=EXCLUDED.last_mode,
|
|
42
|
+
rows_inserted=EXCLUDED.rows_inserted, rows_updated=EXCLUDED.rows_updated,
|
|
43
|
+
rows_deleted=EXCLUDED.rows_deleted, error=EXCLUDED.error
|
|
44
|
+
""", (table, signature, mode, inserted, updated, deleted, error))
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
def cast_expr(src_type: str, tgt_type: str, tgt_maxlen: int | None, ph: str = "%s") -> str:
|
|
2
|
+
# CHAR(n) (bpchar) source is blank-padded; trailing spaces are insignificant.
|
|
3
|
+
# Strip them so the coerced value matches the trimmed value stored in v2.
|
|
4
|
+
if src_type == "character":
|
|
5
|
+
ph = f"rtrim({ph})"
|
|
6
|
+
t = tgt_type
|
|
7
|
+
if t in ("geometry", "geography"):
|
|
8
|
+
return f"({ph})::{t}"
|
|
9
|
+
if t == "character varying" and tgt_maxlen:
|
|
10
|
+
return f"left(({ph})::text, {tgt_maxlen})"
|
|
11
|
+
if t == "text":
|
|
12
|
+
return f"({ph})::text"
|
|
13
|
+
if t in ("integer", "bigint", "smallint"):
|
|
14
|
+
if src_type in ("character varying", "text"):
|
|
15
|
+
return (f"(CASE WHEN btrim(({ph})::text) ~ '^-?[0-9]+$' "
|
|
16
|
+
f"THEN btrim(({ph})::text)::{t} ELSE NULL END)")
|
|
17
|
+
return f"({ph})::{t}"
|
|
18
|
+
if t == "boolean":
|
|
19
|
+
if src_type == "boolean":
|
|
20
|
+
return f"({ph})"
|
|
21
|
+
if src_type in ("bigint", "integer", "smallint", "numeric", "double precision"):
|
|
22
|
+
return (f"(CASE WHEN {ph} IS NULL THEN NULL "
|
|
23
|
+
f"WHEN ({ph})::numeric=0 THEN false ELSE true END)")
|
|
24
|
+
return (f"(CASE WHEN btrim(({ph})::text) IN ('1','true','t','yes','si','y') THEN true "
|
|
25
|
+
f"WHEN btrim(({ph})::text) IN ('0','false','f','no','n','') THEN false ELSE NULL END)")
|
|
26
|
+
if t == "date":
|
|
27
|
+
if src_type == "date":
|
|
28
|
+
return f"({ph})"
|
|
29
|
+
return ("(CASE "
|
|
30
|
+
f"WHEN btrim(({ph})::text) ~ '^[0-9]{{4}}-[0-9]{{2}}-[0-9]{{2}}' THEN substr(btrim(({ph})::text),1,10)::date "
|
|
31
|
+
f"WHEN btrim(({ph})::text) ~ '^[0-9]{{1,2}}/[0-9]{{1,2}}/[0-9]{{4}}$' THEN to_date(btrim(({ph})::text),'DD/MM/YYYY') "
|
|
32
|
+
f"WHEN btrim(({ph})::text) ~ '^[0-9]{{1,2}}-[0-9]{{1,2}}-[0-9]{{4}}$' THEN to_date(btrim(({ph})::text),'DD-MM-YYYY') "
|
|
33
|
+
"ELSE NULL END)")
|
|
34
|
+
if t == "timestamp with time zone":
|
|
35
|
+
return f"({ph})::timestamptz"
|
|
36
|
+
if t == "timestamp without time zone":
|
|
37
|
+
return f"({ph})::timestamp"
|
|
38
|
+
if t == "double precision":
|
|
39
|
+
return f"({ph})::double precision"
|
|
40
|
+
if t == "numeric":
|
|
41
|
+
return f"({ph})::numeric"
|
|
42
|
+
return f"({ph})" # matching/other types: pass the value through
|
|
43
|
+
|
|
44
|
+
def row_hash_sql(columns: list[str]) -> str:
|
|
45
|
+
parts = "||'|'||".join(f"coalesce(\"{c}\"::text,'')" for c in columns)
|
|
46
|
+
return f"md5({parts})" if columns else "md5('')"
|
|
47
|
+
|
|
48
|
+
def plain_row_hash_sql(columns: list[str], col_types: dict) -> str:
|
|
49
|
+
if not columns:
|
|
50
|
+
return "md5('')"
|
|
51
|
+
parts = []
|
|
52
|
+
for c in columns:
|
|
53
|
+
ref = f'"{c}"'
|
|
54
|
+
if col_types.get(c, ("", None))[0] == "character":
|
|
55
|
+
ref = f"rtrim({ref})"
|
|
56
|
+
parts.append(f"coalesce(({ref})::text,'')")
|
|
57
|
+
return "md5(" + "||'|'||".join(parts) + ")"
|
|
58
|
+
|
|
59
|
+
def build_pk_hash_select(table: str, pk: list[str], hash_cols: list[str]) -> str:
|
|
60
|
+
pk_sql = ", ".join(f'"{c}"' for c in pk)
|
|
61
|
+
return f'SELECT {pk_sql}, {row_hash_sql(hash_cols)} FROM public."{table}"'
|
|
62
|
+
|
|
63
|
+
def coerced_row_hash_sql(columns: list[str], src_types: dict, tgt_types: dict, geom: set) -> str:
|
|
64
|
+
if not columns:
|
|
65
|
+
return "md5('')"
|
|
66
|
+
parts = []
|
|
67
|
+
for c in columns:
|
|
68
|
+
tgt_t = "geometry" if c in geom else tgt_types[c][0]
|
|
69
|
+
expr = cast_expr(src_types[c][0], tgt_t, tgt_types[c][1], ph=f'"{c}"')
|
|
70
|
+
parts.append(f"coalesce(({expr})::text,'')")
|
|
71
|
+
return "md5(" + "||'|'||".join(parts) + ")"
|
|
72
|
+
|
|
73
|
+
def build_pk_hash_select_coerced(table: str, pk: list[str], columns: list[str],
|
|
74
|
+
src_types: dict, tgt_types: dict, geom: set) -> str:
|
|
75
|
+
pk_sql = ", ".join(f'"{c}"' for c in pk)
|
|
76
|
+
return (f'SELECT {pk_sql}, '
|
|
77
|
+
f'{coerced_row_hash_sql(columns, src_types, tgt_types, geom)} FROM public."{table}"')
|
|
78
|
+
|
|
79
|
+
def build_insert(table: str, cols: list[str], value_exprs: list[str], fill: dict[str, str]) -> str:
|
|
80
|
+
all_cols = cols + list(fill.keys())
|
|
81
|
+
col_sql = ", ".join(f'"{c}"' for c in all_cols)
|
|
82
|
+
val_sql = ", ".join(value_exprs + list(fill.values()))
|
|
83
|
+
return f'INSERT INTO public."{table}" ({col_sql}) VALUES ({val_sql})'
|
|
84
|
+
|
|
85
|
+
def build_update(table: str, set_cols: list[str], set_exprs: list[str], pk: list[str]) -> str:
|
|
86
|
+
# pk uses NAMED placeholders so the whole statement is named-param (set_exprs
|
|
87
|
+
# carry named %(col)s placeholders from cast_expr; mixing named+positional is illegal).
|
|
88
|
+
assigns = ", ".join(f'"{c}" = {e}' for c, e in zip(set_cols, set_exprs))
|
|
89
|
+
where = " AND ".join(f'"{c}" = %(__pk_{c})s' for c in pk)
|
|
90
|
+
return f'UPDATE public."{table}" SET {assigns} WHERE {where}'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyarchinit-mini
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.5
|
|
4
4
|
Summary: Lightweight archaeological data management system with REST API, Web UI, Desktop GUI, CLI, multi-user authentication, real-time collaboration, analytics dashboard, PyArchInit import/export, Heriverse/ATON export integration, and 3D CRUD viewer
|
|
5
5
|
Home-page: https://github.com/enzococca/pyarchinit-mini
|
|
6
6
|
Author: PyArchInit Team
|
|
@@ -275,7 +275,21 @@ pyarchinit_mini/stratigraph/sync_orchestrator.py
|
|
|
275
275
|
pyarchinit_mini/stratigraph/sync_queue.py
|
|
276
276
|
pyarchinit_mini/stratigraph/sync_state_machine.py
|
|
277
277
|
pyarchinit_mini/stratigraph/uuid_manager.py
|
|
278
|
+
pyarchinit_mini/sync/__init__.py
|
|
279
|
+
pyarchinit_mini/sync/__main__.py
|
|
280
|
+
pyarchinit_mini/sync/config.py
|
|
281
|
+
pyarchinit_mini/sync/diff.py
|
|
282
|
+
pyarchinit_mini/sync/engine.py
|
|
283
|
+
pyarchinit_mini/sync/introspect.py
|
|
284
|
+
pyarchinit_mini/sync/policy.py
|
|
285
|
+
pyarchinit_mini/sync/rowmap.py
|
|
286
|
+
pyarchinit_mini/sync/runner.py
|
|
287
|
+
pyarchinit_mini/sync/state.py
|
|
288
|
+
pyarchinit_mini/sync/sync_config.example.json
|
|
289
|
+
pyarchinit_mini/sync/transform.py
|
|
290
|
+
pyarchinit_mini/translations/en/LC_MESSAGES/messages.mo
|
|
278
291
|
pyarchinit_mini/translations/en/LC_MESSAGES/messages.po
|
|
292
|
+
pyarchinit_mini/translations/it/LC_MESSAGES/messages.mo
|
|
279
293
|
pyarchinit_mini/translations/it/LC_MESSAGES/messages.po
|
|
280
294
|
pyarchinit_mini/utils/__init__.py
|
|
281
295
|
pyarchinit_mini/utils/auth.py
|
|
@@ -451,6 +465,16 @@ tests/integration/test_vocab_routes.py
|
|
|
451
465
|
tests/integration/test_yed_export_route.py
|
|
452
466
|
tests/integration/test_yed_import_routes.py
|
|
453
467
|
tests/integration/test_yed_writer_parity.py
|
|
468
|
+
tests/sync/__init__.py
|
|
469
|
+
tests/sync/conftest.py
|
|
470
|
+
tests/sync/test_config.py
|
|
471
|
+
tests/sync/test_diff.py
|
|
472
|
+
tests/sync/test_engine.py
|
|
473
|
+
tests/sync/test_introspect.py
|
|
474
|
+
tests/sync/test_policy.py
|
|
475
|
+
tests/sync/test_rowmap.py
|
|
476
|
+
tests/sync/test_runner.py
|
|
477
|
+
tests/sync/test_transform.py
|
|
454
478
|
tests/unit/__init__.py
|
|
455
479
|
tests/unit/test_ai_matrix_apply.py
|
|
456
480
|
tests/unit/test_ai_matrix_extractor_parse.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyarchinit-mini"
|
|
7
|
-
version = "2.9.
|
|
7
|
+
version = "2.9.5"
|
|
8
8
|
description = "Lightweight archaeological data management system with REST API, Web UI, Desktop GUI, CLI, multi-user authentication, real-time collaboration, analytics dashboard, PyArchInit import/export, Heriverse/ATON export integration, and 3D CRUD viewer"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "GPL-2.0"}
|
|
@@ -174,6 +174,7 @@ exclude = ["docs*", "examples*", "scripts*", "test_*"]
|
|
|
174
174
|
"*" = ["logo/*.png"]
|
|
175
175
|
pyarchinit_mini = [
|
|
176
176
|
"*.yaml", "*.yml", "*.json",
|
|
177
|
+
"sync/*.json",
|
|
177
178
|
"data/*.db", "data/*.sql",
|
|
178
179
|
"graphml_converter/templates/*.graphml",
|
|
179
180
|
"web_interface/templates/*.html",
|