pyarchinit-mini 1.9.28__py3-none-any.whl

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.
Files changed (281) hide show
  1. pyarchinit_mini/__init__.py +40 -0
  2. pyarchinit_mini/api/__init__.py +92 -0
  3. pyarchinit_mini/api/auth.py +312 -0
  4. pyarchinit_mini/api/dependencies.py +63 -0
  5. pyarchinit_mini/api/graphml.py +160 -0
  6. pyarchinit_mini/api/inventario.py +107 -0
  7. pyarchinit_mini/api/schemas.py +186 -0
  8. pyarchinit_mini/api/site.py +220 -0
  9. pyarchinit_mini/api/us.py +107 -0
  10. pyarchinit_mini/cli/__init__.py +7 -0
  11. pyarchinit_mini/cli/export_import_cli.py +289 -0
  12. pyarchinit_mini/cli/extended_matrix_import.py +101 -0
  13. pyarchinit_mini/cli/graphml_cli.py +219 -0
  14. pyarchinit_mini/cli/harris_import.py +574 -0
  15. pyarchinit_mini/cli/harris_template.py +323 -0
  16. pyarchinit_mini/cli/migrate.py +202 -0
  17. pyarchinit_mini/cli/pyarchinit_import_export_cli.py +428 -0
  18. pyarchinit_mini/cli_interface/__init__.py +1 -0
  19. pyarchinit_mini/cli_interface/cli_app.py +529 -0
  20. pyarchinit_mini/config/__init__.py +0 -0
  21. pyarchinit_mini/config/connection_manager.py +286 -0
  22. pyarchinit_mini/config/em_node_config_manager.py +452 -0
  23. pyarchinit_mini/config/em_node_types.yaml +349 -0
  24. pyarchinit_mini/database/__init__.py +13 -0
  25. pyarchinit_mini/database/connection.py +168 -0
  26. pyarchinit_mini/database/database_creator.py +290 -0
  27. pyarchinit_mini/database/manager.py +231 -0
  28. pyarchinit_mini/database/migration_scripts/__init__.py +7 -0
  29. pyarchinit_mini/database/migration_scripts/add_file_path.py +152 -0
  30. pyarchinit_mini/database/migration_scripts/add_i18n_columns.py +312 -0
  31. pyarchinit_mini/database/migration_scripts/add_tipo_documento.py +154 -0
  32. pyarchinit_mini/database/migration_scripts/change_us_area_to_text.py +321 -0
  33. pyarchinit_mini/database/migration_scripts/change_us_area_to_text_simple.py +230 -0
  34. pyarchinit_mini/database/migrations.py +232 -0
  35. pyarchinit_mini/database/postgres_installer.py +375 -0
  36. pyarchinit_mini/database/schemas.py +177 -0
  37. pyarchinit_mini/desktop_gui/__init__.py +51 -0
  38. pyarchinit_mini/desktop_gui/analytics_dialog.py +228 -0
  39. pyarchinit_mini/desktop_gui/assets/logo.png +0 -0
  40. pyarchinit_mini/desktop_gui/dialogs.py +1984 -0
  41. pyarchinit_mini/desktop_gui/excel_import_dialog.py +380 -0
  42. pyarchinit_mini/desktop_gui/export_import_dialog.py +313 -0
  43. pyarchinit_mini/desktop_gui/graphml_export_dialog.py +221 -0
  44. pyarchinit_mini/desktop_gui/gui_app.py +106 -0
  45. pyarchinit_mini/desktop_gui/harris_matrix_editor.py +970 -0
  46. pyarchinit_mini/desktop_gui/i18n.py +191 -0
  47. pyarchinit_mini/desktop_gui/icons.py +70 -0
  48. pyarchinit_mini/desktop_gui/inventario_dialog_extended.py +966 -0
  49. pyarchinit_mini/desktop_gui/main_window.py +1826 -0
  50. pyarchinit_mini/desktop_gui/media_manager_advanced.py +141 -0
  51. pyarchinit_mini/desktop_gui/postgres_installer_dialog.py +357 -0
  52. pyarchinit_mini/desktop_gui/pyarchinit_import_export_dialog.py +585 -0
  53. pyarchinit_mini/desktop_gui/thesaurus_dialog.py +463 -0
  54. pyarchinit_mini/desktop_gui/us_dialog_extended.py +2122 -0
  55. pyarchinit_mini/dto/__init__.py +16 -0
  56. pyarchinit_mini/dto/inventario_dto.py +57 -0
  57. pyarchinit_mini/dto/site_dto.py +62 -0
  58. pyarchinit_mini/dto/us_dto.py +237 -0
  59. pyarchinit_mini/exceptions.py +23 -0
  60. pyarchinit_mini/graphml_converter/__init__.py +47 -0
  61. pyarchinit_mini/graphml_converter/converter.py +343 -0
  62. pyarchinit_mini/graphml_converter/dot_parser.py +1331 -0
  63. pyarchinit_mini/graphml_converter/em_palette.py +355 -0
  64. pyarchinit_mini/graphml_converter/graphml_builder.py +657 -0
  65. pyarchinit_mini/graphml_converter/graphml_exporter.py +1048 -0
  66. pyarchinit_mini/graphml_converter/pure_networkx_exporter.py +719 -0
  67. pyarchinit_mini/graphml_converter/svg_resources.py +244 -0
  68. pyarchinit_mini/graphml_converter/templates/EM_palette.graphml +658 -0
  69. pyarchinit_mini/graphml_converter/x11_colors.py +678 -0
  70. pyarchinit_mini/graphml_converter/yed_template.py +365 -0
  71. pyarchinit_mini/harris_matrix/__init__.py +11 -0
  72. pyarchinit_mini/harris_matrix/enhanced_visualizer.py +465 -0
  73. pyarchinit_mini/harris_matrix/matrix_generator.py +1244 -0
  74. pyarchinit_mini/harris_matrix/matrix_visualizer.py +368 -0
  75. pyarchinit_mini/harris_matrix/pyarchinit_visualizer.py +581 -0
  76. pyarchinit_mini/i18n/__init__.py +15 -0
  77. pyarchinit_mini/i18n/flask_babel_config.py +94 -0
  78. pyarchinit_mini/i18n/locale_manager.py +142 -0
  79. pyarchinit_mini/mcp_server/__init__.py +22 -0
  80. pyarchinit_mini/mcp_server/__main__.py +45 -0
  81. pyarchinit_mini/mcp_server/blender_client.py +525 -0
  82. pyarchinit_mini/mcp_server/config.py +181 -0
  83. pyarchinit_mini/mcp_server/event_stream.py +282 -0
  84. pyarchinit_mini/mcp_server/graphml_parser.py +612 -0
  85. pyarchinit_mini/mcp_server/http_server.py +501 -0
  86. pyarchinit_mini/mcp_server/period_filter.py +362 -0
  87. pyarchinit_mini/mcp_server/prompts/__init__.py +18 -0
  88. pyarchinit_mini/mcp_server/prompts/base_prompt.py +23 -0
  89. pyarchinit_mini/mcp_server/prompts/period_visualization_prompt.py +25 -0
  90. pyarchinit_mini/mcp_server/prompts/stratigraphic_model_prompt.py +25 -0
  91. pyarchinit_mini/mcp_server/prompts/us_description_prompt.py +25 -0
  92. pyarchinit_mini/mcp_server/proxy_generator.py +470 -0
  93. pyarchinit_mini/mcp_server/resources/__init__.py +24 -0
  94. pyarchinit_mini/mcp_server/resources/base_resource.py +79 -0
  95. pyarchinit_mini/mcp_server/resources/graphml_resource.py +382 -0
  96. pyarchinit_mini/mcp_server/resources/periods_resource.py +52 -0
  97. pyarchinit_mini/mcp_server/resources/relationships_resource.py +52 -0
  98. pyarchinit_mini/mcp_server/resources/sites_resource.py +52 -0
  99. pyarchinit_mini/mcp_server/resources/us_resource.py +52 -0
  100. pyarchinit_mini/mcp_server/server.py +564 -0
  101. pyarchinit_mini/mcp_server/tools/__init__.py +24 -0
  102. pyarchinit_mini/mcp_server/tools/base_tool.py +119 -0
  103. pyarchinit_mini/mcp_server/tools/batch_insert_tool.py +393 -0
  104. pyarchinit_mini/mcp_server/tools/build_3d_tool.py +524 -0
  105. pyarchinit_mini/mcp_server/tools/chatgpt_fetch_tool.py +183 -0
  106. pyarchinit_mini/mcp_server/tools/chatgpt_search_tool.py +130 -0
  107. pyarchinit_mini/mcp_server/tools/configure_em_nodes_tool.py +427 -0
  108. pyarchinit_mini/mcp_server/tools/create_database_tool.py +118 -0
  109. pyarchinit_mini/mcp_server/tools/create_harris_matrix_tool.py +421 -0
  110. pyarchinit_mini/mcp_server/tools/data_import_parser_tool.py +695 -0
  111. pyarchinit_mini/mcp_server/tools/data_management_tool.py +262 -0
  112. pyarchinit_mini/mcp_server/tools/database_manager_tool.py +200 -0
  113. pyarchinit_mini/mcp_server/tools/delete_data_tool.py +288 -0
  114. pyarchinit_mini/mcp_server/tools/export_harris_matrix_graphml_tool.py +184 -0
  115. pyarchinit_mini/mcp_server/tools/export_tool.py +32 -0
  116. pyarchinit_mini/mcp_server/tools/filter_tool.py +32 -0
  117. pyarchinit_mini/mcp_server/tools/generate_report_tool.py +679 -0
  118. pyarchinit_mini/mcp_server/tools/get_schema_tool.py +224 -0
  119. pyarchinit_mini/mcp_server/tools/import_excel_tool.py +270 -0
  120. pyarchinit_mini/mcp_server/tools/insert_data_tool.py +390 -0
  121. pyarchinit_mini/mcp_server/tools/manage_services_tool.py +507 -0
  122. pyarchinit_mini/mcp_server/tools/material_tool.py +32 -0
  123. pyarchinit_mini/mcp_server/tools/media_management_tool.py +494 -0
  124. pyarchinit_mini/mcp_server/tools/position_tool.py +32 -0
  125. pyarchinit_mini/mcp_server/tools/pyarchinit_sync_tool.py +172 -0
  126. pyarchinit_mini/mcp_server/tools/resolve_conflicts_tool.py +377 -0
  127. pyarchinit_mini/mcp_server/tools/service_management_tool.py +104 -0
  128. pyarchinit_mini/mcp_server/tools/thesaurus_management_tool.py +420 -0
  129. pyarchinit_mini/mcp_server/tools/update_data_tool.py +360 -0
  130. pyarchinit_mini/mcp_server/tools/upload_file_tool.py +112 -0
  131. pyarchinit_mini/mcp_server/tools/validate_relationship_format_tool.py +327 -0
  132. pyarchinit_mini/mcp_server/tools/validate_relationship_integrity_tool.py +532 -0
  133. pyarchinit_mini/mcp_server/tools/validate_stratigraphic_relationships_tool.py +261 -0
  134. pyarchinit_mini/mcp_server/tools/validate_stratigraphy_tool.py +363 -0
  135. pyarchinit_mini/media_manager/__init__.py +9 -0
  136. pyarchinit_mini/media_manager/media_handler.py +322 -0
  137. pyarchinit_mini/models/__init__.py +35 -0
  138. pyarchinit_mini/models/base.py +32 -0
  139. pyarchinit_mini/models/datazione.py +68 -0
  140. pyarchinit_mini/models/extended_matrix.py +44 -0
  141. pyarchinit_mini/models/harris_matrix.py +117 -0
  142. pyarchinit_mini/models/inventario_materiali.py +238 -0
  143. pyarchinit_mini/models/media.py +109 -0
  144. pyarchinit_mini/models/site.py +96 -0
  145. pyarchinit_mini/models/thesaurus.py +179 -0
  146. pyarchinit_mini/models/us.py +291 -0
  147. pyarchinit_mini/models/user.py +78 -0
  148. pyarchinit_mini/pdf_export/__init__.py +9 -0
  149. pyarchinit_mini/pdf_export/pdf_generator.py +1048 -0
  150. pyarchinit_mini/pdf_export/pdf_generator_backup.py +1013 -0
  151. pyarchinit_mini/pdf_export/pyarchinit_finds_template.py +404 -0
  152. pyarchinit_mini/pdf_export/pyarchinit_inventory_template.py +353 -0
  153. pyarchinit_mini/pdf_export/usm_implementation.py +465 -0
  154. pyarchinit_mini/s3d_integration/__init__.py +9 -0
  155. pyarchinit_mini/s3d_integration/model_manager.py +234 -0
  156. pyarchinit_mini/s3d_integration/s3d_converter.py +848 -0
  157. pyarchinit_mini/scripts/__init__.py +3 -0
  158. pyarchinit_mini/scripts/auto_translate.py +679 -0
  159. pyarchinit_mini/scripts/configure_claude_desktop.py +277 -0
  160. pyarchinit_mini/scripts/create_admin_user.py +152 -0
  161. pyarchinit_mini/scripts/create_correct_stratigraphy_sample.py +373 -0
  162. pyarchinit_mini/scripts/create_italian_sample_database.py +302 -0
  163. pyarchinit_mini/scripts/create_sample_for_webapp.py +463 -0
  164. pyarchinit_mini/scripts/create_sample_with_50_us.py +353 -0
  165. pyarchinit_mini/scripts/generate_test_3d_model.py +323 -0
  166. pyarchinit_mini/scripts/load_italian_as_main.py +39 -0
  167. pyarchinit_mini/scripts/load_sample_as_main.py +73 -0
  168. pyarchinit_mini/scripts/migrate_relationships.py +165 -0
  169. pyarchinit_mini/scripts/populate_sample_data.py +498 -0
  170. pyarchinit_mini/scripts/populate_simple_data.py +213 -0
  171. pyarchinit_mini/scripts/setup_auth.py +112 -0
  172. pyarchinit_mini/scripts/setup_user_env.py +316 -0
  173. pyarchinit_mini/scripts/test_cascade_delete.py +91 -0
  174. pyarchinit_mini/scripts/test_relationship_fix.py +128 -0
  175. pyarchinit_mini/scripts/update_sample_relationships.py +136 -0
  176. pyarchinit_mini/scripts/update_urls_and_versions.py +312 -0
  177. pyarchinit_mini/scripts/verify_docs.py +312 -0
  178. pyarchinit_mini/services/__init__.py +19 -0
  179. pyarchinit_mini/services/analytics_service.py +242 -0
  180. pyarchinit_mini/services/command_parser.py +159 -0
  181. pyarchinit_mini/services/datazione_service.py +244 -0
  182. pyarchinit_mini/services/export_import_service.py +430 -0
  183. pyarchinit_mini/services/extended_matrix_excel_parser.py +708 -0
  184. pyarchinit_mini/services/import_export_service.py +2381 -0
  185. pyarchinit_mini/services/inventario_service.py +347 -0
  186. pyarchinit_mini/services/mcp_executor.py +206 -0
  187. pyarchinit_mini/services/media_service.py +458 -0
  188. pyarchinit_mini/services/periodizzazione_service.py +417 -0
  189. pyarchinit_mini/services/relationship_sync_service.py +400 -0
  190. pyarchinit_mini/services/site_service.py +328 -0
  191. pyarchinit_mini/services/thesaurus_service.py +358 -0
  192. pyarchinit_mini/services/us_service.py +446 -0
  193. pyarchinit_mini/services/user_service.py +293 -0
  194. pyarchinit_mini/translations/en/LC_MESSAGES/messages.mo +0 -0
  195. pyarchinit_mini/translations/en/LC_MESSAGES/messages.po +5110 -0
  196. pyarchinit_mini/translations/it/LC_MESSAGES/messages.mo +0 -0
  197. pyarchinit_mini/translations/it/LC_MESSAGES/messages.po +4798 -0
  198. pyarchinit_mini/translations/messages.pot +0 -0
  199. pyarchinit_mini/utils/__init__.py +27 -0
  200. pyarchinit_mini/utils/auth.py +143 -0
  201. pyarchinit_mini/utils/exceptions.py +38 -0
  202. pyarchinit_mini/utils/relationship_validator.py +388 -0
  203. pyarchinit_mini/utils/stratigraphic_validator.py +613 -0
  204. pyarchinit_mini/utils/validators.py +230 -0
  205. pyarchinit_mini/web_interface/app.py +4152 -0
  206. pyarchinit_mini/web_interface/auth_routes.py +263 -0
  207. pyarchinit_mini/web_interface/em_node_config_routes.py +280 -0
  208. pyarchinit_mini/web_interface/excel_import_routes.py +336 -0
  209. pyarchinit_mini/web_interface/harris_creator_routes.py +568 -0
  210. pyarchinit_mini/web_interface/pyarchinit_import_export_routes.py +888 -0
  211. pyarchinit_mini/web_interface/s3d_routes.py +361 -0
  212. pyarchinit_mini/web_interface/socketio_events.py +537 -0
  213. pyarchinit_mini/web_interface/static/css/style.css +4 -0
  214. pyarchinit_mini/web_interface/static/images/favicon.ico +0 -0
  215. pyarchinit_mini/web_interface/static/images/logo.png +0 -0
  216. pyarchinit_mini/web_interface/static/images/pyarchinit-mini-logo.png +0 -0
  217. pyarchinit_mini/web_interface/static/js/OrbitControls.js +1045 -0
  218. pyarchinit_mini/web_interface/static/js/harris_creator_editor.js +989 -0
  219. pyarchinit_mini/web_interface/static/js/stratigraphic_layout.js +782 -0
  220. pyarchinit_mini/web_interface/static/js/three-d-viewer.js +670 -0
  221. pyarchinit_mini/web_interface/static/js/three.min.js +6 -0
  222. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.bin +0 -0
  223. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.gltf +92 -0
  224. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.mtl +71 -0
  225. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.obj +244 -0
  226. pyarchinit_mini/web_interface/templates/3d_builder/index.html +2092 -0
  227. pyarchinit_mini/web_interface/templates/3d_viewer/viewer.html +259 -0
  228. pyarchinit_mini/web_interface/templates/admin/database.html +1140 -0
  229. pyarchinit_mini/web_interface/templates/admin/database_connect.html +188 -0
  230. pyarchinit_mini/web_interface/templates/admin/database_info.html +171 -0
  231. pyarchinit_mini/web_interface/templates/admin/database_upload.html +112 -0
  232. pyarchinit_mini/web_interface/templates/analytics/dashboard.html +414 -0
  233. pyarchinit_mini/web_interface/templates/auth/login.html +52 -0
  234. pyarchinit_mini/web_interface/templates/auth/users.html +217 -0
  235. pyarchinit_mini/web_interface/templates/base.html +765 -0
  236. pyarchinit_mini/web_interface/templates/blender_viewer.html +1285 -0
  237. pyarchinit_mini/web_interface/templates/components/language_switcher.html +47 -0
  238. pyarchinit_mini/web_interface/templates/dashboard.html +226 -0
  239. pyarchinit_mini/web_interface/templates/datazioni/list.html +62 -0
  240. pyarchinit_mini/web_interface/templates/em_node_config/index.html +430 -0
  241. pyarchinit_mini/web_interface/templates/excel_import/index.html +391 -0
  242. pyarchinit_mini/web_interface/templates/export/export_import.html +240 -0
  243. pyarchinit_mini/web_interface/templates/harris_creator/editor.html +373 -0
  244. pyarchinit_mini/web_interface/templates/harris_creator/index.html +196 -0
  245. pyarchinit_mini/web_interface/templates/harris_matrix/graphml_export.html +300 -0
  246. pyarchinit_mini/web_interface/templates/harris_matrix/large_graph_message.html +108 -0
  247. pyarchinit_mini/web_interface/templates/harris_matrix/stratigraph_viewer.html +474 -0
  248. pyarchinit_mini/web_interface/templates/harris_matrix/view.html +97 -0
  249. pyarchinit_mini/web_interface/templates/harris_matrix/view_graphviz.html +202 -0
  250. pyarchinit_mini/web_interface/templates/harris_matrix/viewer_3d_integrated.html +1288 -0
  251. pyarchinit_mini/web_interface/templates/inventario/form.html +605 -0
  252. pyarchinit_mini/web_interface/templates/inventario/list.html +109 -0
  253. pyarchinit_mini/web_interface/templates/media/list.html +293 -0
  254. pyarchinit_mini/web_interface/templates/media/upload.html +125 -0
  255. pyarchinit_mini/web_interface/templates/periodizzazione/form.html +81 -0
  256. pyarchinit_mini/web_interface/templates/periodizzazione/list.html +102 -0
  257. pyarchinit_mini/web_interface/templates/periodizzazione/periods.html +107 -0
  258. pyarchinit_mini/web_interface/templates/pyarchinit_import_export/index.html +928 -0
  259. pyarchinit_mini/web_interface/templates/sites/detail.html +128 -0
  260. pyarchinit_mini/web_interface/templates/sites/form.html +315 -0
  261. pyarchinit_mini/web_interface/templates/sites/list.html +273 -0
  262. pyarchinit_mini/web_interface/templates/thesaurus/list.html +290 -0
  263. pyarchinit_mini/web_interface/templates/us/form.html +788 -0
  264. pyarchinit_mini/web_interface/templates/us/list.html +165 -0
  265. pyarchinit_mini/web_interface/templates/validation/report.html +253 -0
  266. pyarchinit_mini/web_interface/test_prova_extended_matrix.graphml +177 -0
  267. pyarchinit_mini/web_interface/three_d_builder_routes.py +1554 -0
  268. pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.graphml +1792 -0
  269. pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +2115 -0
  270. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_heriverse.json +2132 -0
  271. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.graphml +2001 -0
  272. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.json +1782 -0
  273. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +1457 -0
  274. pyarchinit_mini-1.9.28.dist-info/METADATA +2141 -0
  275. pyarchinit_mini-1.9.28.dist-info/RECORD +281 -0
  276. pyarchinit_mini-1.9.28.dist-info/WHEEL +5 -0
  277. pyarchinit_mini-1.9.28.dist-info/entry_points.txt +18 -0
  278. pyarchinit_mini-1.9.28.dist-info/top_level.txt +2 -0
  279. tests/__init__.py +1 -0
  280. tests/conftest.py +88 -0
  281. tests/unit/test_site_service.py +106 -0
@@ -0,0 +1,40 @@
1
+ """
2
+ PyArchInit-Mini: Standalone Archaeological Data Management System
3
+
4
+ A lightweight, modular version of PyArchInit focused on core archaeological
5
+ data management functionality without GIS dependencies.
6
+
7
+ Features:
8
+ - Site management with complete CRUD operations
9
+ - Stratigraphic Unit (US) management (49 fields, 6 tabs)
10
+ - Material inventory management (37 fields, 8 tabs, ICCD thesaurus)
11
+ - Harris Matrix generation (Matplotlib + Graphviz with 4 grouping modes)
12
+ - Stratigraphic validation (paradoxes, cycles, auto-fix)
13
+ - Multi-database support (PostgreSQL/SQLite upload/connect)
14
+ - PDF export (Sites, US, Inventario, Harris Matrix)
15
+ - Excel/CSV export and batch import
16
+ - Multi-user authentication with role-based permissions (Admin, Operator, Viewer)
17
+ - Real-time collaboration with WebSocket notifications (Flask-SocketIO)
18
+ - Analytics dashboard with 8 chart types (Chart.js for web, matplotlib for desktop)
19
+ - REST API interface (FastAPI with JWT authentication)
20
+ - Web UI interface (Flask with session-based auth) - 100% Desktop GUI parity
21
+ - Desktop GUI interface (Tkinter)
22
+ - CLI interface
23
+ - Scalable and modular architecture
24
+ """
25
+
26
+ __version__ = "1.9.23"
27
+ __author__ = "PyArchInit Team"
28
+ __email__ = "enzo.ccc@gmail.com"
29
+
30
+ from .database.manager import DatabaseManager
31
+ from .services.site_service import SiteService
32
+ from .services.us_service import USService
33
+ from .services.inventario_service import InventarioService
34
+
35
+ __all__ = [
36
+ "DatabaseManager",
37
+ "SiteService",
38
+ "USService",
39
+ "InventarioService"
40
+ ]
@@ -0,0 +1,92 @@
1
+ """
2
+ FastAPI REST API for PyArchInit-Mini
3
+ """
4
+
5
+ from fastapi import FastAPI
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from pyarchinit_mini import __version__
8
+ from .site import router as site_router
9
+ from .us import router as us_router
10
+ from .inventario import router as inventario_router
11
+ from .auth import router as auth_router
12
+ from .graphml import router as graphml_router
13
+
14
+ def create_app(database_url: str = None) -> FastAPI:
15
+ """
16
+ Create and configure FastAPI application
17
+
18
+ Args:
19
+ database_url: Database connection URL
20
+
21
+ Returns:
22
+ Configured FastAPI app
23
+ """
24
+ app = FastAPI(
25
+ title="PyArchInit-Mini API",
26
+ description="REST API for archaeological data management",
27
+ version=__version__,
28
+ docs_url="/docs",
29
+ redoc_url="/redoc"
30
+ )
31
+
32
+ # Add CORS middleware
33
+ app.add_middleware(
34
+ CORSMiddleware,
35
+ allow_origins=["*"], # Configure appropriately for production
36
+ allow_credentials=True,
37
+ allow_methods=["*"],
38
+ allow_headers=["*"],
39
+ )
40
+
41
+ # Include routers
42
+ app.include_router(auth_router) # Auth routes already have /api/auth prefix
43
+ app.include_router(site_router, prefix="/api/v1/sites", tags=["sites"])
44
+ app.include_router(us_router, prefix="/api/v1/us", tags=["stratigraphic-units"])
45
+ app.include_router(inventario_router, prefix="/api/v1/inventario", tags=["inventory"])
46
+ app.include_router(graphml_router, prefix="/api/graphml", tags=["graphml-converter"])
47
+
48
+ # Store database URL in app state
49
+ if database_url:
50
+ app.state.database_url = database_url
51
+
52
+ @app.get("/")
53
+ async def root():
54
+ return {
55
+ "message": "PyArchInit-Mini API",
56
+ "version": __version__,
57
+ "docs": "/docs"
58
+ }
59
+
60
+ @app.get("/health")
61
+ async def health_check():
62
+ return {"status": "healthy"}
63
+
64
+ return app
65
+
66
+
67
+ def run_server():
68
+ """
69
+ Entry point for running the API server via console script.
70
+ """
71
+ import uvicorn
72
+ import os
73
+
74
+ # Get configuration from environment or use defaults
75
+ host = os.getenv("PYARCHINIT_API_HOST", "0.0.0.0")
76
+ port = int(os.getenv("PYARCHINIT_API_PORT", "8000"))
77
+ reload = os.getenv("PYARCHINIT_API_RELOAD", "false").lower() == "true"
78
+
79
+ print(f"Starting PyArchInit-Mini API server on {host}:{port}")
80
+ print(f"API Documentation: http://{host if host != '0.0.0.0' else 'localhost'}:{port}/docs")
81
+
82
+ # Run the server
83
+ uvicorn.run(
84
+ "pyarchinit_mini.api:create_app",
85
+ host=host,
86
+ port=port,
87
+ reload=reload,
88
+ factory=True
89
+ )
90
+
91
+
92
+ __all__ = ["create_app", "run_server"]
@@ -0,0 +1,312 @@
1
+ """
2
+ Authentication API endpoints
3
+ """
4
+
5
+ from typing import Optional
6
+ from datetime import timedelta
7
+
8
+ from fastapi import APIRouter, Depends, HTTPException, status
9
+ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
10
+ from pydantic import BaseModel, EmailStr
11
+
12
+ from pyarchinit_mini.database.manager import DatabaseManager
13
+ from pyarchinit_mini.services.user_service import UserService
14
+ from pyarchinit_mini.models.user import UserRole
15
+ from pyarchinit_mini.utils.auth import create_access_token, decode_access_token
16
+ from pyarchinit_mini.api.dependencies import get_database_manager
17
+
18
+
19
+ # OAuth2 scheme
20
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login")
21
+
22
+
23
+ # Pydantic schemas
24
+ class Token(BaseModel):
25
+ """Token response"""
26
+ access_token: str
27
+ token_type: str
28
+
29
+
30
+ class TokenData(BaseModel):
31
+ """Token payload data"""
32
+ username: Optional[str] = None
33
+
34
+
35
+ class UserResponse(BaseModel):
36
+ """User response schema"""
37
+ id: int
38
+ username: str
39
+ email: str
40
+ full_name: Optional[str] = None
41
+ role: str
42
+ is_active: bool
43
+ is_superuser: bool
44
+
45
+
46
+ class UserCreate(BaseModel):
47
+ """User creation schema"""
48
+ username: str
49
+ email: EmailStr
50
+ password: str
51
+ full_name: Optional[str] = None
52
+ role: UserRole = UserRole.VIEWER
53
+
54
+
55
+ class UserUpdate(BaseModel):
56
+ """User update schema"""
57
+ email: Optional[EmailStr] = None
58
+ full_name: Optional[str] = None
59
+ role: Optional[UserRole] = None
60
+ is_active: Optional[bool] = None
61
+ password: Optional[str] = None
62
+
63
+
64
+ # Router
65
+ router = APIRouter(prefix="/api/auth", tags=["authentication"])
66
+
67
+
68
+ async def get_current_user(
69
+ token: str = Depends(oauth2_scheme),
70
+ db_manager: DatabaseManager = Depends(get_database_manager)
71
+ ) -> dict:
72
+ """
73
+ Get current authenticated user from token
74
+
75
+ Args:
76
+ token: JWT token
77
+ db_manager: Database manager
78
+
79
+ Returns:
80
+ dict: Current user data
81
+
82
+ Raises:
83
+ HTTPException: If authentication fails
84
+ """
85
+ credentials_exception = HTTPException(
86
+ status_code=status.HTTP_401_UNAUTHORIZED,
87
+ detail="Could not validate credentials",
88
+ headers={"WWW-Authenticate": "Bearer"},
89
+ )
90
+
91
+ # Decode token
92
+ payload = decode_access_token(token)
93
+ if payload is None:
94
+ raise credentials_exception
95
+
96
+ username: str = payload.get("sub")
97
+ if username is None:
98
+ raise credentials_exception
99
+
100
+ # Get user
101
+ user_service = UserService(db_manager)
102
+ user = user_service.get_user_by_username(username)
103
+
104
+ if user is None:
105
+ raise credentials_exception
106
+
107
+ if not user["is_active"]:
108
+ raise HTTPException(
109
+ status_code=status.HTTP_403_FORBIDDEN,
110
+ detail="User is inactive"
111
+ )
112
+
113
+ return user
114
+
115
+
116
+ async def get_current_active_admin(
117
+ current_user: dict = Depends(get_current_user)
118
+ ) -> dict:
119
+ """
120
+ Verify current user is admin
121
+
122
+ Args:
123
+ current_user: Current user from token
124
+
125
+ Returns:
126
+ dict: Current user data
127
+
128
+ Raises:
129
+ HTTPException: If user is not admin
130
+ """
131
+ if current_user["role"] != UserRole.ADMIN.value and not current_user["is_superuser"]:
132
+ raise HTTPException(
133
+ status_code=status.HTTP_403_FORBIDDEN,
134
+ detail="Not enough permissions"
135
+ )
136
+
137
+ return current_user
138
+
139
+
140
+ @router.post("/login", response_model=Token)
141
+ async def login(
142
+ form_data: OAuth2PasswordRequestForm = Depends(),
143
+ db_manager: DatabaseManager = Depends(get_database_manager)
144
+ ):
145
+ """
146
+ Login endpoint - Returns JWT token
147
+
148
+ Args:
149
+ form_data: Username and password
150
+ db_manager: Database manager
151
+
152
+ Returns:
153
+ Token: Access token
154
+ """
155
+ user_service = UserService(db_manager)
156
+ user = user_service.authenticate_user(form_data.username, form_data.password)
157
+
158
+ if not user:
159
+ raise HTTPException(
160
+ status_code=status.HTTP_401_UNAUTHORIZED,
161
+ detail="Incorrect username or password",
162
+ headers={"WWW-Authenticate": "Bearer"},
163
+ )
164
+
165
+ # Create access token
166
+ access_token_expires = timedelta(minutes=30)
167
+ access_token = create_access_token(
168
+ data={"sub": user["username"]},
169
+ expires_delta=access_token_expires
170
+ )
171
+
172
+ return {"access_token": access_token, "token_type": "bearer"}
173
+
174
+
175
+ @router.get("/me", response_model=UserResponse)
176
+ async def get_me(current_user: dict = Depends(get_current_user)):
177
+ """
178
+ Get current user information
179
+
180
+ Args:
181
+ current_user: Current authenticated user
182
+
183
+ Returns:
184
+ UserResponse: Current user data
185
+ """
186
+ return current_user
187
+
188
+
189
+ @router.post("/register", response_model=UserResponse)
190
+ async def register(
191
+ user_data: UserCreate,
192
+ db_manager: DatabaseManager = Depends(get_database_manager),
193
+ current_user: dict = Depends(get_current_active_admin)
194
+ ):
195
+ """
196
+ Register a new user (admin only)
197
+
198
+ Args:
199
+ user_data: User creation data
200
+ db_manager: Database manager
201
+ current_user: Current admin user
202
+
203
+ Returns:
204
+ UserResponse: Created user
205
+ """
206
+ user_service = UserService(db_manager)
207
+
208
+ try:
209
+ user = user_service.create_user(
210
+ username=user_data.username,
211
+ email=user_data.email,
212
+ password=user_data.password,
213
+ full_name=user_data.full_name,
214
+ role=user_data.role
215
+ )
216
+ return user
217
+ except ValueError as e:
218
+ raise HTTPException(
219
+ status_code=status.HTTP_400_BAD_REQUEST,
220
+ detail=str(e)
221
+ )
222
+
223
+
224
+ @router.get("/users", response_model=list[UserResponse])
225
+ async def list_users(
226
+ db_manager: DatabaseManager = Depends(get_database_manager),
227
+ current_user: dict = Depends(get_current_active_admin)
228
+ ):
229
+ """
230
+ List all users (admin only)
231
+
232
+ Args:
233
+ db_manager: Database manager
234
+ current_user: Current admin user
235
+
236
+ Returns:
237
+ List[UserResponse]: List of all users
238
+ """
239
+ user_service = UserService(db_manager)
240
+ users = user_service.get_all_users()
241
+ return users
242
+
243
+
244
+ @router.put("/users/{user_id}", response_model=UserResponse)
245
+ async def update_user(
246
+ user_id: int,
247
+ user_data: UserUpdate,
248
+ db_manager: DatabaseManager = Depends(get_database_manager),
249
+ current_user: dict = Depends(get_current_active_admin)
250
+ ):
251
+ """
252
+ Update user (admin only)
253
+
254
+ Args:
255
+ user_id: User ID to update
256
+ user_data: Update data
257
+ db_manager: Database manager
258
+ current_user: Current admin user
259
+
260
+ Returns:
261
+ UserResponse: Updated user
262
+ """
263
+ user_service = UserService(db_manager)
264
+
265
+ # Prepare update dict (exclude None values)
266
+ updates = {k: v for k, v in user_data.dict().items() if v is not None}
267
+
268
+ user = user_service.update_user(user_id, **updates)
269
+
270
+ if not user:
271
+ raise HTTPException(
272
+ status_code=status.HTTP_404_NOT_FOUND,
273
+ detail="User not found"
274
+ )
275
+
276
+ return user
277
+
278
+
279
+ @router.delete("/users/{user_id}")
280
+ async def delete_user(
281
+ user_id: int,
282
+ db_manager: DatabaseManager = Depends(get_database_manager),
283
+ current_user: dict = Depends(get_current_active_admin)
284
+ ):
285
+ """
286
+ Delete user (admin only)
287
+
288
+ Args:
289
+ user_id: User ID to delete
290
+ db_manager: Database manager
291
+ current_user: Current admin user
292
+
293
+ Returns:
294
+ dict: Success message
295
+ """
296
+ # Prevent deleting yourself
297
+ if user_id == current_user["id"]:
298
+ raise HTTPException(
299
+ status_code=status.HTTP_400_BAD_REQUEST,
300
+ detail="Cannot delete your own account"
301
+ )
302
+
303
+ user_service = UserService(db_manager)
304
+ deleted = user_service.delete_user(user_id)
305
+
306
+ if not deleted:
307
+ raise HTTPException(
308
+ status_code=status.HTTP_404_NOT_FOUND,
309
+ detail="User not found"
310
+ )
311
+
312
+ return {"message": "User deleted successfully"}
@@ -0,0 +1,63 @@
1
+ """
2
+ FastAPI dependencies for PyArchInit-Mini
3
+ """
4
+
5
+ from fastapi import Depends, HTTPException, Request
6
+ from ..database.connection import DatabaseConnection
7
+ from ..database.manager import DatabaseManager
8
+ from ..services.site_service import SiteService
9
+ from ..services.us_service import USService
10
+ from ..services.inventario_service import InventarioService
11
+
12
+ # Global database connection (will be initialized by app)
13
+ _db_connection = None
14
+
15
+ def get_database_connection() -> DatabaseConnection:
16
+ """Get database connection dependency"""
17
+ global _db_connection
18
+ if _db_connection is None:
19
+ raise HTTPException(status_code=500, detail="Database not initialized")
20
+ return _db_connection
21
+
22
+ def get_database_manager(
23
+ db_conn: DatabaseConnection = Depends(get_database_connection)
24
+ ) -> DatabaseManager:
25
+ """Get database manager dependency"""
26
+ return DatabaseManager(db_conn)
27
+
28
+ def get_site_service(
29
+ db_manager: DatabaseManager = Depends(get_database_manager)
30
+ ) -> SiteService:
31
+ """Get site service dependency"""
32
+ return SiteService(db_manager)
33
+
34
+ def get_us_service(
35
+ db_manager: DatabaseManager = Depends(get_database_manager)
36
+ ) -> USService:
37
+ """Get US service dependency"""
38
+ return USService(db_manager)
39
+
40
+ def get_inventario_service(
41
+ db_manager: DatabaseManager = Depends(get_database_manager)
42
+ ) -> InventarioService:
43
+ """Get inventario service dependency"""
44
+ return InventarioService(db_manager)
45
+
46
+ def init_database(database_url: str):
47
+ """Initialize global database connection"""
48
+ global _db_connection
49
+ _db_connection = DatabaseConnection.from_url(database_url)
50
+
51
+ # Initialize database with migrations
52
+ _db_connection.initialize_database()
53
+
54
+ # Test connection
55
+ if not _db_connection.test_connection():
56
+ raise Exception("Failed to establish database connection")
57
+
58
+ def close_database():
59
+ """Close global database connection"""
60
+ global _db_connection
61
+ if _db_connection:
62
+ _db_connection.close()
63
+ _db_connection = None
@@ -0,0 +1,160 @@
1
+ """
2
+ GraphML Converter API endpoints
3
+ """
4
+ from fastapi import APIRouter, UploadFile, File, Form, HTTPException
5
+ from fastapi.responses import Response, FileResponse
6
+ from typing import Optional
7
+ import tempfile
8
+ import os
9
+
10
+ from pyarchinit_mini.graphml_converter import (
11
+ convert_dot_to_graphml,
12
+ convert_dot_content_to_graphml,
13
+ get_template_path
14
+ )
15
+
16
+ router = APIRouter()
17
+
18
+
19
+ @router.post("/convert",
20
+ summary="Convert DOT file to GraphML",
21
+ description="Upload a Graphviz DOT file and convert it to yEd-compatible GraphML format")
22
+ async def convert_dot_file(
23
+ file: UploadFile = File(..., description="DOT file to convert"),
24
+ title: str = Form("", description="Diagram title/header"),
25
+ reverse_epochs: bool = Form(False, description="Whether to reverse epoch ordering")
26
+ ):
27
+ """
28
+ Convert uploaded DOT file to GraphML format.
29
+
30
+ Args:
31
+ file: DOT file upload
32
+ title: Optional diagram title
33
+ reverse_epochs: Whether to reverse epoch ordering (default: False)
34
+
35
+ Returns:
36
+ GraphML file content
37
+
38
+ Example:
39
+ curl -X POST "http://localhost:8000/api/graphml/convert" \
40
+ -F "file=@harris_matrix.dot" \
41
+ -F "title=Pompei - Regio VI" \
42
+ -F "reverse_epochs=false"
43
+ """
44
+ if not file.filename.endswith('.dot'):
45
+ raise HTTPException(status_code=400, detail="File must have .dot extension")
46
+
47
+ try:
48
+ # Read uploaded file content
49
+ content = await file.read()
50
+ dot_content = content.decode('utf-8')
51
+
52
+ # Convert to GraphML
53
+ graphml_content = convert_dot_content_to_graphml(
54
+ dot_content,
55
+ title=title,
56
+ reverse_epochs=reverse_epochs
57
+ )
58
+
59
+ if graphml_content is None:
60
+ raise HTTPException(status_code=500, detail="Conversion failed")
61
+
62
+ # Return GraphML content
63
+ filename = file.filename.replace('.dot', '.graphml')
64
+ return Response(
65
+ content=graphml_content,
66
+ media_type="application/xml",
67
+ headers={
68
+ "Content-Disposition": f"attachment; filename={filename}"
69
+ }
70
+ )
71
+
72
+ except UnicodeDecodeError:
73
+ raise HTTPException(status_code=400, detail="File must be UTF-8 encoded text")
74
+ except Exception as e:
75
+ raise HTTPException(status_code=500, detail=f"Conversion error: {str(e)}")
76
+
77
+
78
+ @router.post("/convert-content",
79
+ summary="Convert DOT content to GraphML",
80
+ description="Convert DOT content string to GraphML format")
81
+ async def convert_dot_content(
82
+ dot_content: str = Form(..., description="DOT file content as string"),
83
+ title: str = Form("", description="Diagram title/header"),
84
+ reverse_epochs: bool = Form(False, description="Whether to reverse epoch ordering")
85
+ ):
86
+ """
87
+ Convert DOT content string to GraphML format.
88
+
89
+ Args:
90
+ dot_content: DOT file content as string
91
+ title: Optional diagram title
92
+ reverse_epochs: Whether to reverse epoch ordering (default: False)
93
+
94
+ Returns:
95
+ GraphML content as string
96
+
97
+ Example:
98
+ curl -X POST "http://localhost:8000/api/graphml/convert-content" \
99
+ -F "dot_content=digraph { \"US 100\" -> \"US 101\"; }" \
100
+ -F "title=Test Site"
101
+ """
102
+ try:
103
+ graphml_content = convert_dot_content_to_graphml(
104
+ dot_content,
105
+ title=title,
106
+ reverse_epochs=reverse_epochs
107
+ )
108
+
109
+ if graphml_content is None:
110
+ raise HTTPException(status_code=500, detail="Conversion failed")
111
+
112
+ return Response(
113
+ content=graphml_content,
114
+ media_type="application/xml"
115
+ )
116
+
117
+ except Exception as e:
118
+ raise HTTPException(status_code=500, detail=f"Conversion error: {str(e)}")
119
+
120
+
121
+ @router.get("/template",
122
+ summary="Download yEd GraphML template",
123
+ description="Download the EM_palette.graphml template used for Harris Matrix diagrams")
124
+ async def download_template():
125
+ """
126
+ Download the yEd GraphML template file.
127
+
128
+ Returns:
129
+ EM_palette.graphml template file
130
+
131
+ Example:
132
+ curl -X GET "http://localhost:8000/api/graphml/template" -o EM_palette.graphml
133
+ """
134
+ template_path = get_template_path()
135
+
136
+ if not os.path.exists(template_path):
137
+ raise HTTPException(status_code=404, detail="Template file not found")
138
+
139
+ return FileResponse(
140
+ path=template_path,
141
+ media_type="application/xml",
142
+ filename="EM_palette.graphml"
143
+ )
144
+
145
+
146
+ @router.get("/health",
147
+ summary="Health check",
148
+ description="Check if the GraphML converter service is running")
149
+ async def health_check():
150
+ """
151
+ Health check endpoint.
152
+
153
+ Returns:
154
+ Service status
155
+ """
156
+ return {
157
+ "status": "ok",
158
+ "service": "graphml-converter",
159
+ "version": "1.0.0"
160
+ }