s3dgraphy 1.6.0.dev46__tar.gz → 1.6.0.dev48__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.
- {s3dgraphy-1.6.0.dev46/src/s3dgraphy.egg-info → s3dgraphy-1.6.0.dev48}/PKG-INFO +1 -1
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/pyproject.toml +1 -1
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/__init__.py +1 -1
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/api.py +78 -6
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/container.py +151 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/contract/connector.py +4 -3
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/crdt.py +154 -20
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/editorial.py +45 -3
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/rdf_importer.py +3 -2
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/property_source.py +3 -1
- s3dgraphy-1.6.0.dev48/src/s3dgraphy/resources/alignment.py +273 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/locate.py +14 -3
- s3dgraphy-1.6.0.dev48/src/s3dgraphy/resources/moved.py +149 -0
- s3dgraphy-1.6.0.dev48/src/s3dgraphy/resources/object_store.py +174 -0
- s3dgraphy-1.6.0.dev48/src/s3dgraphy/resources/storage_rows.py +163 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/graph_projector.py +77 -23
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48/src/s3dgraphy.egg-info}/PKG-INFO +1 -1
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy.egg-info/SOURCES.txt +6 -0
- s3dgraphy-1.6.0.dev48/tests/test_bucket_alignment.py +108 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_crdt.py +259 -1
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_editorial.py +28 -0
- s3dgraphy-1.6.0.dev48/tests/test_storage_rows.py +77 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/LICENSE +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/MANIFEST.in +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/README.md +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/setup.cfg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/acquisition_descriptor.schema.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/acquisition_mappings/ercolano.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/acquisition_mappings/fs.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/acquisition_mappings/uri.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/datamodel_translations.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em.ttl +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_document_types.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_extractor_types.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_palette_icons.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_qualia_types.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_qualia_types_additions.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_state_symbols.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/em_visual_rules.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/hdto_extension.ttl +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/new_qualia_template.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/node_registry.generated.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/outdated_s3dgraphy.ttl +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/outdated_s3dgraphy_nomapping.ttl +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/s3Dgraphy_connections_datamodel.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/s3Dgraphy_connections_datamodel.json.v155.bak +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/s3Dgraphy_node_datamodel.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/ActivityNodeGroup.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/EMNarrative.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/EMNarrative.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/EpochNode.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/ParadataNodeGroup.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/RSF.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/RSF.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/SE.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/SE_old.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/SE_old.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/SF.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/SF.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/TSU.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/US.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/US.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USD.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USD.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USVn.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USVn.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USVs.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/USVs.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/UTR.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/VSF.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/VSF.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/author.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/author.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/author_ai.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/author_ai.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/combiner.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/combiner.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/container.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/continuity.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/continuity.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/document.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/document.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/00_transformation.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/01_topographicnetwork.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/02_pointcloud.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/03_mesh.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/04_points.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/05_lines.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/06_polygons.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/07_DEM.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/08_ortophoto.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/09_photos.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/10_laserscanner.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_computer.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_drone.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_gnss.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_optical.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_scanner.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_sensor.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/11_device_station.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/12_gnss_survey.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/13_field_drawing.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/14_recording_sheet.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/15_decimation.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/16_georeferencing.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/17_format_conversion.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/18_classification.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/dtc/19_vectorization.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/embargo.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/embargo.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/extractor.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/extractor.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/gcp_set.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/generic_node.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/geo_position.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/graph.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/license.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/license.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/link.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/narrative.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/narrative.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/play.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/property.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/property.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/proxy.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/registration_transform.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/representation_model.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/representation_model_doc.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/representation_model_sf.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/resource_file.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/semantic_shape.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serSU.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serSU.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serUSD.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serUSV.png +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serUSVn.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/serUSVs.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/tileset.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/version_gltf.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/version_mesh.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/version_scene.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/2D/version_tiles.svg +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/RSF.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/SF.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/TSU.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/US.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/USD.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/USVn.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/USVs.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/VSF.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/combiner.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/continuity.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/document.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/extractor.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/property.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/serSU.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/serUSD.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/src/3D/serUSV.glb +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/JSON_config/version_for_cases.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/acquisition/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/acquisition/acquire.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/acquisition/descriptor.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/acquisition/mapping.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/ai_validation.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/annotation/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/annotation/migrate_reading.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/annotation/paradata.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/annotation/reading.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/LICENSE +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/chronontology.jsonld +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/getty_aat.jsonld +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/getty_tgn.jsonld +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/periodo.jsonld +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/authorities/snapshots/provenance.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/classification.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/contract/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/contract/consumer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/contract/core.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/contract/reference.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/data/StratiMiner_Extraction_Prompt.md +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/datamodel.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/diagnostics.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dissemination.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/capture.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/corpus.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/devices.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/ingest.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/neighbourhood.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/dtc/residency.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/edges/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/edges/connection_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/edges/connections_loader.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/edges/edge.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/docx_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/emjson_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/canvas_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/edge_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/epoch_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/graphml_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/graphml_patcher.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/group_node_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/node_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/node_registry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/palette_resources.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/paradata_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/paradata_image_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/paradata_node_generators.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/table_node_generator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/graphml/utils.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/html_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/ipynb_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/json_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/latex_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/rdf_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/exporter/unified_xlsx_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/aton.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/gltf.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/migrate.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/proxy.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/reading_glb.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/store_backed.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/geometry/wkt.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/graph.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/hdto.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/iiif.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/base_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/csv_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/emjson_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/fmpxml_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/import_graphml.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/mapped_xlsx_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/metashape_project.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/pyarchinit_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/qualia_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/sheet_header.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/source_text.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/unified_xlsx_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/xlsx_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/importer/xml_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/indices.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/labels.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/language.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/links.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/authoring.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/emdb/generic_specialfind_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/emdb/site_properties_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/emdb/usm_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/generic/excel_to_graphml_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/pyarchinit/pyarchinit_us_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/registry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/source_list/em_sourcelist_it.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/source_list/source_list_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/template_emdb_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/mappings/template_pyarchinit_mapping.json +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/merge/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/merge/graph_merger.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/multigraph/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/multigraph/multigraph.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/bake.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/generation.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/query.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/registry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/narrative/site_story.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/annotation_region_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/author_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/base_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/combiner_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/document_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/dtc_acquisition_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/dtc_device_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/dtc_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/dtc_process_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/embargo_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/epoch_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/extractor_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/geo_position_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/georeferencing_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/graph_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/group_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/hdt_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/heritage_entity_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/license_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/narrative_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/paradata_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/project_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/property_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/representation_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/resource_file_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/resource_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/semantic_shape_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/stratigraphic_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/study_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/nodes/translation_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/ownership.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/paradata_view.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/photogrammetry/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/photogrammetry/delta.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/project_tree.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/publication.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/rapporti.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resolvers/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resolvers/builtin_rules.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resolvers/property_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/addresses.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/files.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/fs_backend.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/minio_backend.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/tiles3tz.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/resources/versions.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/rights.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/shelf/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/shelf/core.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/spatiotemporal.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/stamp/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/stamp/absorb.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/stamp/emit.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/stamp/hints.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/stamp/identity.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/study.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/_db_handle.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/_legacy_paradata_svgs.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/_workspace.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/conflict_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/edge_registry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/graph_ingestor.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/graphml_writer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/group_projector.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/group_store.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/ingest_result.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/paradata_store.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/pyarchinit_pg_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/rapporti.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/uuid7.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/vocab_provider_core.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/vocab_types.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_classifier.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_detector.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_group_walker.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_import_pipeline.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_rapporti_policy.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/sync/yed_table_parser.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/templates/em_data_template.xlsx +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/templates/em_palette_template.graphml +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/temporal/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/temporal/inference_engine.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/consumer_drift.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/datamodel_i18n.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/deliverable_report.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/glyph_sheet.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/glyphs_from_svg.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/node_finder.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/sync_node_datamodel.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/tools/wheel_drift.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/transforms/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/transforms/aux_tracking.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/transforms/compact.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/transforms/materialize_continuity.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/translation.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/utils/__init__.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/utils/utils.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/utils/visual_layout.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy/zero_hour.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy.egg-info/dependency_links.txt +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy.egg-info/requires.txt +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/src/s3dgraphy.egg-info/top_level.txt +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_acquisition.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_acquisition_fs.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_add_resource.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_ai_validation_nodes.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_alternative_labels.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_api_surface.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_asset_dtc_protocol.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_asset_versions.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_aton_shapes.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_attach_only.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_authority_projection.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_authority_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_blend_locator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_canonical_document_rename.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_canvas_metadata_import.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_capture_acquisition.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_capture_rdf_class.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_chronology_on_request.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_coating_unit.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_composite_node_name.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_connection_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_consumer_drift.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_container.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_container_layouts.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_containment_tpq.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_contract.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_contract_consumer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_convert_command.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_cycle_message_is_cheap.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_datamodel_fingerprint.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_datamodel_i18n.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_deterministic_ids.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_em_sourcelist.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_file_set_stamp.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_graphml_without_a_database.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_image_set_texturing.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_not_georeferenced.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_one_act_n_outputs.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev29_ttl_round_trip.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dev30_decisions.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_devices.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dissemination_tombstones.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dove_sta_il_testo.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dtc_corpus.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dtc_ingest.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dtc_neighbourhood.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dtc_projection.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_dtc_residency.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_edge_outside_graph.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_edge_ui_phrases.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_em_ttl_matches_the_datamodels.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_emjson_no_drawing_keys.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_emjson_roundtrip.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_emjson_schema_version.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_epoch_properties_and_sub_epochs.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_epoch_undated_import.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_explicit_node_type_marker.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_extracted_from_unit.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_filtered_import.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_fmpxml_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_fs_backend.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_functional_units.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_georeference_scene.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_gltf_stitch.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_glyph_paths.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_graph_header_code.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_graph_helpers_indexed.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_graph_indices_alive.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_graph_indices_edges.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_graph_scope_migration.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_hdto_projection.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_hdto_study.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_header_key_aliases.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_i_generi_dei_passi.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_iiif.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_il_modo_d_accesso.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_il_modo_dal_relay.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_il_proprietario_si_legge.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_il_riallineamento.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_importer_edge_hygiene.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_ipynb_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_issue27_small_points.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_la_lingua_alla_nascita.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_la_lingua_dei_dati.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_la_lingua_nell_op.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_la_riga_d_intestazione.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_latex_exporter.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_le_traduzioni.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_lod_levels.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_lossless_roundtrip.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_mapping_authoring.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_mapping_csv_and_relations.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_masonry_unit.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_material_color.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_merge_conflicts.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_metashape_project.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_migrate_legacy_proxy.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_minio_backend.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_authorship.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_bake_docx.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_figures.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_generation.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_mentions.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_query.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_scaffolder.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_site_place.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_narrative_unvalidated_export.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_node_datamodel_registry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_node_finder.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_node_type_map_integrity.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_one_resolver.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_one_spelling_writers.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_op_vocabulary.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_pg_importer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_photogrammetry_delta.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_physical_relation_spellings.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_piu_indirizzi.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_promotion.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_property_as_source.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_property_owners.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_proxy_resource.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_proxy_retype.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_psx_locator.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_pyarchinit_tier2.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_qualia_dai_d7_d8.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_rdf_embedding.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_rdf_reverse_edges.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_rdf_roundtrip.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reading_coords.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reading_glb.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reading_migration.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reading_place.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reading_rdf.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_recompute_warnings.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_release.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reproject.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_file_node.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_files_implicit.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_layer.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_representations.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_revision.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_resource_tier.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_reverse_edges.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_rm_container_node_group.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_semantic_purity.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_shelf.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_shelf_facets.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_shelf_hatting.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_shelf_role_uri_table.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_shipped_mappings.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_source_list_mapping.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_source_text.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_spatiotemporal_entities.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_stable_study_code.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_stamp.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_stamp_hints.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_stamp_title_description.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_store_backed_geometry.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_stratiminer_api.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_study_metadata.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_tileset_resource.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_ttl_roundtrip.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_unit_definition.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_verifica_provenance.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_version_for.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_visual_assets.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_wheel_drift.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_xlsx_containment_and_unknown_bounds.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_xlsx_importer_graph_init.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_xlsx_source_column.py +0 -0
- {s3dgraphy-1.6.0.dev46 → s3dgraphy-1.6.0.dev48}/tests/test_zero_hour.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: s3dgraphy
|
|
3
|
-
Version: 1.6.0.
|
|
3
|
+
Version: 1.6.0.dev48
|
|
4
4
|
Summary: 3D Stratigraphic Graph Management Library for archaeological and heritage applications
|
|
5
5
|
Author-email: Emanuel Demetrescu <emanuel.demetrescu@cnr.it>
|
|
6
6
|
Maintainer-email: Emanuel Demetrescu <emanuel.demetrescu@cnr.it>
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "s3dgraphy"
|
|
7
|
-
version = "1.6.0.
|
|
7
|
+
version = "1.6.0.dev48"
|
|
8
8
|
description = "3D Stratigraphic Graph Management Library for archaeological and heritage applications"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -646,6 +646,16 @@ def merge_containers(container, other):
|
|
|
646
646
|
return merge_into_container(container, other)
|
|
647
647
|
|
|
648
648
|
|
|
649
|
+
def merge_graphs(container, graph_ids: Optional[List[str]] = None):
|
|
650
|
+
"""One graph for the overall view of the graphs of ``container`` (all,
|
|
651
|
+
or ``graph_ids``): nodes united by id, edges deduplicated by
|
|
652
|
+
``(source, type, target)``, the links between them as edges. Returns
|
|
653
|
+
``(graph, report)``; the container is not touched. See
|
|
654
|
+
:func:`s3dgraphy.container.merge_graphs`."""
|
|
655
|
+
from .container import merge_graphs as _merge
|
|
656
|
+
return _merge(container, graph_ids)
|
|
657
|
+
|
|
658
|
+
|
|
649
659
|
# ── HDT-O: the study, its place, the heritage it is about ────────────────────
|
|
650
660
|
|
|
651
661
|
def declare_hdto(graph: Graph, *, study=None, place=None, about=None,
|
|
@@ -804,7 +814,7 @@ def set_field(node, field: str, value, *, author=None,
|
|
|
804
814
|
coming out of its tombstone.
|
|
805
815
|
"""
|
|
806
816
|
from .crdt import Clock, write_field
|
|
807
|
-
from .editorial import normalize_orcid,
|
|
817
|
+
from .editorial import normalize_orcid, now_op_iso
|
|
808
818
|
|
|
809
819
|
if field in ("data.lang", "data.from_lang") and value not in (None, ""):
|
|
810
820
|
# a node's language is a BCP 47 tag; an invalid one is refused, not stored
|
|
@@ -812,7 +822,7 @@ def set_field(node, field: str, value, *, author=None,
|
|
|
812
822
|
check_language_tag(value)
|
|
813
823
|
payload = _node_payload_view(node)
|
|
814
824
|
write_field(payload, field, value,
|
|
815
|
-
Clock(ts=at or
|
|
825
|
+
Clock(ts=at or now_op_iso(), by=normalize_orcid(author)))
|
|
816
826
|
_write_back(node, payload, field)
|
|
817
827
|
|
|
818
828
|
|
|
@@ -826,10 +836,10 @@ def clear_field(node, field: str, *, author=None,
|
|
|
826
836
|
correctly, and wrongly, hand the value back.
|
|
827
837
|
"""
|
|
828
838
|
from .crdt import Clock, clear_field as _clear
|
|
829
|
-
from .editorial import normalize_orcid,
|
|
839
|
+
from .editorial import normalize_orcid, now_op_iso
|
|
830
840
|
|
|
831
841
|
payload = _node_payload_view(node)
|
|
832
|
-
_clear(payload, field, Clock(ts=at or
|
|
842
|
+
_clear(payload, field, Clock(ts=at or now_op_iso(), by=normalize_orcid(author)))
|
|
833
843
|
_write_back(node, payload, field)
|
|
834
844
|
|
|
835
845
|
|
|
@@ -873,7 +883,7 @@ def stamp_field(node, field: str, *, by=None, at: Optional[str] = None) -> None:
|
|
|
873
883
|
but `set_field` is the one to use: it cannot be half-done.
|
|
874
884
|
"""
|
|
875
885
|
from .crdt import Clock, set_field_clock
|
|
876
|
-
from .editorial import normalize_orcid,
|
|
886
|
+
from .editorial import normalize_orcid, now_op_iso
|
|
877
887
|
|
|
878
888
|
data = getattr(node, "data", None)
|
|
879
889
|
if not isinstance(data, dict):
|
|
@@ -881,7 +891,7 @@ def stamp_field(node, field: str, *, by=None, at: Optional[str] = None) -> None:
|
|
|
881
891
|
node.data = data
|
|
882
892
|
payload = {"data": data}
|
|
883
893
|
set_field_clock(payload, field,
|
|
884
|
-
Clock(ts=at or
|
|
894
|
+
Clock(ts=at or now_op_iso(), by=normalize_orcid(by)))
|
|
885
895
|
|
|
886
896
|
|
|
887
897
|
def unstamped_fields(node) -> List[str]:
|
|
@@ -3058,6 +3068,68 @@ def resolve_file(entry: Dict[str, Any], **kwargs) -> Dict[str, Any]:
|
|
|
3058
3068
|
return resolve(entry, **kwargs)
|
|
3059
3069
|
|
|
3060
3070
|
|
|
3071
|
+
# ── S1 · the Storage list and «find moved» (E.D., 11 Oct 2026) ────────────────
|
|
3072
|
+
def storage_rows(graph: Graph, results: Sequence[Dict[str, Any]],
|
|
3073
|
+
graph_name: str = "") -> List[Dict[str, Any]]:
|
|
3074
|
+
"""The files of ``graph`` as ONE list: master, versions by computed level,
|
|
3075
|
+
files of a set, links of a document — with uses, tier, document, the RMs
|
|
3076
|
+
that use each, and its state. ``results`` is :func:`resolve_files`. EMtools
|
|
3077
|
+
and EMStudio draw these rows. See :mod:`s3dgraphy.resources.storage_rows`."""
|
|
3078
|
+
from .resources.storage_rows import storage_rows as _rows
|
|
3079
|
+
return _rows(graph, list(results), graph_name)
|
|
3080
|
+
|
|
3081
|
+
|
|
3082
|
+
def find_moved_files(graph: Graph, results: Sequence[Dict[str, Any]],
|
|
3083
|
+
folders: Sequence[str], **kwargs) -> List[Dict[str, Any]]:
|
|
3084
|
+
"""For the files that are ``missing`` (or an empty copy), the candidates found
|
|
3085
|
+
in ``folders`` — by sha256, then by name and size — each saying HOW it was
|
|
3086
|
+
recognised. Proposes only: nothing is changed. See
|
|
3087
|
+
:mod:`s3dgraphy.resources.moved`."""
|
|
3088
|
+
from .resources.moved import find_moved
|
|
3089
|
+
return find_moved(graph, list(results), folders, **kwargs)
|
|
3090
|
+
|
|
3091
|
+
|
|
3092
|
+
# ── B1 · disk ↔ bucket: the two copies, and what may be let go (E.D., 11 Oct 2026) ──
|
|
3093
|
+
def open_object_store(name: Optional[str] = None, config: Any = None):
|
|
3094
|
+
"""The object store of the Resource layer — any S3-compatible one (MinIO
|
|
3095
|
+
today). ``S3_*`` environment, ``EM_OBJECT_STORE`` to choose another
|
|
3096
|
+
implementation (:func:`s3dgraphy.resources.object_store.register_store`)."""
|
|
3097
|
+
from .resources.object_store import open_store
|
|
3098
|
+
return open_store(name, config)
|
|
3099
|
+
|
|
3100
|
+
|
|
3101
|
+
def bucket_alignment(graph: Graph, results: Sequence[Dict[str, Any]], store: Any = None, *,
|
|
3102
|
+
deep: bool = False, **kwargs) -> List[Dict[str, Any]]:
|
|
3103
|
+
"""How the disk copy and the bucket copy of each file stand: ``aligned`` (the
|
|
3104
|
+
sha256 of both, read now), ``same_size``, ``differ``, ``disk_only``,
|
|
3105
|
+
``bucket_only``, ``neither``, ``unknown``. Reads only. See
|
|
3106
|
+
:mod:`s3dgraphy.resources.alignment`."""
|
|
3107
|
+
from .resources.alignment import bucket_alignment as _al
|
|
3108
|
+
return _al(graph, list(results), store or open_object_store(), deep=deep, **kwargs)
|
|
3109
|
+
|
|
3110
|
+
|
|
3111
|
+
def plan_free_local(graph: Graph, aligned: Sequence[Dict[str, Any]], **kwargs) -> List[Dict[str, Any]]:
|
|
3112
|
+
"""The files whose local copy may be freed (aligned, verified): ``safe`` for a
|
|
3113
|
+
distribution, ``confirm`` for a master or an original, each with its warning."""
|
|
3114
|
+
from .resources.alignment import free_plan
|
|
3115
|
+
return free_plan(graph, list(aligned), **kwargs)
|
|
3116
|
+
|
|
3117
|
+
|
|
3118
|
+
def free_local_copies(plan: Sequence[Dict[str, Any]], store: Any = None, **kwargs) -> List[Dict[str, Any]]:
|
|
3119
|
+
"""Free the local copies of a plan: the bytes are compared again just before
|
|
3120
|
+
each one leaves; moved to a quarantine folder, or deleted with
|
|
3121
|
+
``permanent=True``; a master only with ``confirm_masters=True``."""
|
|
3122
|
+
from .resources.alignment import free_local
|
|
3123
|
+
return free_local(list(plan), store or open_object_store(), **kwargs)
|
|
3124
|
+
|
|
3125
|
+
|
|
3126
|
+
def promote_to_bucket(graph: Graph, resource_id: str, path: str, store: Any = None, **kwargs) -> Dict[str, Any]:
|
|
3127
|
+
"""Upload, READ BACK and verify, then record the bucket as the primary address
|
|
3128
|
+
and keep the disk path as an address too."""
|
|
3129
|
+
from .resources.alignment import promote_verified
|
|
3130
|
+
return promote_verified(graph, resource_id, path, store or open_object_store(), **kwargs)
|
|
3131
|
+
|
|
3132
|
+
|
|
3061
3133
|
# ── C1 · the standard tree of an EM project (E.D., 4 Oct 2026) ─────────────────
|
|
3062
3134
|
def create_em_project(parent: str, name: str, **kwargs) -> Dict[str, Any]:
|
|
3063
3135
|
"""«New EM project…»: EM/ (DosCo/, proxies/), RB/, SB/, RM/, README.md,
|
|
@@ -1030,3 +1030,154 @@ def merge_into_container(container: Container, other: Container) -> MergeReport:
|
|
|
1030
1030
|
# lie about how much has happened.
|
|
1031
1031
|
bump_version(container)
|
|
1032
1032
|
return report
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
#: the id of the graph :func:`merge_graphs` returns
|
|
1036
|
+
MERGED_GRAPH_ID = "merged"
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
def merge_graphs(container: Container,
|
|
1040
|
+
graph_ids: Optional[Iterable[str]] = None
|
|
1041
|
+
) -> Tuple[Graph, Dict[str, Any]]:
|
|
1042
|
+
"""One graph for the overall view of several graphs of ``container`` —
|
|
1043
|
+
the site whole again, after :meth:`GraphProjector.populate_container`
|
|
1044
|
+
made one graph per saggio (s3Dgraphy#36).
|
|
1045
|
+
|
|
1046
|
+
Each saggio is a study of its own (E.D., 12 Oct 2026): its graph carries
|
|
1047
|
+
a copy of the paradata it shares with the others (documents, authors,
|
|
1048
|
+
epochs, places), with the SAME id. Summing the graphs counts those twice;
|
|
1049
|
+
this does not:
|
|
1050
|
+
|
|
1051
|
+
* **nodes** united by id — the identity of a node shared between graphs
|
|
1052
|
+
is its id, never its label (two documents named «D.01» in two studies
|
|
1053
|
+
may be two documents, and stay two);
|
|
1054
|
+
* **edges** deduplicated by ``(source, type, target)``, the definition of
|
|
1055
|
+
«the same relation» :func:`_merge_graph_into` uses;
|
|
1056
|
+
* **links** (:mod:`s3dgraphy.links`) between two merged graphs become
|
|
1057
|
+
ordinary edges, with the link's id, type and attributes; a link whose
|
|
1058
|
+
other end is not among them stays out, and the report names it.
|
|
1059
|
+
|
|
1060
|
+
The first graph (in ``graph_ids`` order, else the container's) gives the
|
|
1061
|
+
version of a node; when another graph has the same id with different
|
|
1062
|
+
content (the editorial stamps aside, as in a merge), the report says so
|
|
1063
|
+
— node, graphs, which one was kept, which fields diverge. It does not
|
|
1064
|
+
choose in silence. The same for an edge whose attributes differ.
|
|
1065
|
+
|
|
1066
|
+
Reads only: the container, its graphs and their links are not touched
|
|
1067
|
+
(the merged graph holds copies), and nothing is written to file.
|
|
1068
|
+
|
|
1069
|
+
Returns ``(graph, report)``; ``report`` is a dict: ``graphs``,
|
|
1070
|
+
``nodes_in`` / ``nodes`` / ``nodes_merged`` (rows read, nodes kept, copies
|
|
1071
|
+
folded), the same three for ``edges``, ``links_resolved``,
|
|
1072
|
+
``links_unresolved`` (one sentence each), ``conflicts`` (nodes),
|
|
1073
|
+
``edge_conflicts``, ``warnings``.
|
|
1074
|
+
"""
|
|
1075
|
+
import copy
|
|
1076
|
+
from .links import links_of_graph
|
|
1077
|
+
|
|
1078
|
+
ids = list(graph_ids) if graph_ids is not None else container.graph_ids()
|
|
1079
|
+
unknown = [gid for gid in ids if gid not in container.graphs]
|
|
1080
|
+
if unknown:
|
|
1081
|
+
raise ValueError(f"no graph {', '.join(map(repr, unknown))} in this container")
|
|
1082
|
+
|
|
1083
|
+
merged = Graph(MERGED_GRAPH_ID, name="merged view")
|
|
1084
|
+
auto_geo = [n.node_id for n in merged.nodes]
|
|
1085
|
+
report: Dict[str, Any] = {
|
|
1086
|
+
"graphs": list(ids), "nodes_in": 0, "nodes": 0, "nodes_merged": 0,
|
|
1087
|
+
"edges_in": 0, "edges": 0, "edges_merged": 0,
|
|
1088
|
+
"links_resolved": 0, "links_unresolved": [],
|
|
1089
|
+
"conflicts": [], "edge_conflicts": [], "warnings": []}
|
|
1090
|
+
|
|
1091
|
+
nodes: Dict[str, Any] = {}
|
|
1092
|
+
origin: Dict[str, str] = {}
|
|
1093
|
+
content: Dict[str, Dict[str, Any]] = {}
|
|
1094
|
+
contested: Dict[str, Dict[str, Any]] = {}
|
|
1095
|
+
for gid in ids:
|
|
1096
|
+
for node in container.graphs[gid].nodes:
|
|
1097
|
+
report["nodes_in"] += 1
|
|
1098
|
+
snap = _content_of(_node_snapshot(node))
|
|
1099
|
+
if node.node_id not in nodes:
|
|
1100
|
+
nodes[node.node_id] = copy.deepcopy(node)
|
|
1101
|
+
origin[node.node_id] = gid
|
|
1102
|
+
content[node.node_id] = snap
|
|
1103
|
+
continue
|
|
1104
|
+
report["nodes_merged"] += 1
|
|
1105
|
+
if snap == content[node.node_id]:
|
|
1106
|
+
continue
|
|
1107
|
+
entry = contested.get(node.node_id)
|
|
1108
|
+
if entry is None:
|
|
1109
|
+
entry = contested[node.node_id] = {
|
|
1110
|
+
"node_id": node.node_id, "name": getattr(node, "name", None),
|
|
1111
|
+
"kept_from": origin[node.node_id],
|
|
1112
|
+
"graphs": [origin[node.node_id]], "fields": []}
|
|
1113
|
+
report["conflicts"].append(entry)
|
|
1114
|
+
entry["graphs"].append(gid)
|
|
1115
|
+
for name in _diverging_fields(content[node.node_id], snap):
|
|
1116
|
+
if name not in entry["fields"]:
|
|
1117
|
+
entry["fields"].append(name)
|
|
1118
|
+
|
|
1119
|
+
edges: Dict[Tuple[str, str, str], Any] = {}
|
|
1120
|
+
edge_origin: Dict[Tuple[str, str, str], str] = {}
|
|
1121
|
+
edge_ids = set()
|
|
1122
|
+
|
|
1123
|
+
def take(edge, gid: str) -> None:
|
|
1124
|
+
key = (edge.edge_source, edge.edge_type, edge.edge_target)
|
|
1125
|
+
attrs = getattr(edge, "attributes", None) or {}
|
|
1126
|
+
if key in edges:
|
|
1127
|
+
report["edges_merged"] += 1
|
|
1128
|
+
if attrs != (getattr(edges[key], "attributes", None) or {}):
|
|
1129
|
+
report["edge_conflicts"].append({
|
|
1130
|
+
"edge": list(key), "edge_id": edges[key].edge_id,
|
|
1131
|
+
"kept_from": edge_origin[key], "other": gid})
|
|
1132
|
+
return
|
|
1133
|
+
edge_id = edge.edge_id
|
|
1134
|
+
# two graphs may have minted the same id for two relations
|
|
1135
|
+
while edge_id in edge_ids:
|
|
1136
|
+
edge_id = f"{edge_id}_merged"
|
|
1137
|
+
kept = copy.deepcopy(edge)
|
|
1138
|
+
kept.edge_id = edge_id
|
|
1139
|
+
edges[key], edge_origin[key] = kept, gid
|
|
1140
|
+
edge_ids.add(edge_id)
|
|
1141
|
+
|
|
1142
|
+
for gid in ids:
|
|
1143
|
+
for edge in container.graphs[gid].edges:
|
|
1144
|
+
report["edges_in"] += 1
|
|
1145
|
+
take(edge, gid)
|
|
1146
|
+
|
|
1147
|
+
from .edges import Edge
|
|
1148
|
+
chosen = set(ids)
|
|
1149
|
+
for gid in ids:
|
|
1150
|
+
for link in links_of_graph(container.graphs[gid]):
|
|
1151
|
+
target = link["target"]
|
|
1152
|
+
where = f"link '{link['id']}' of the graph '{gid}'"
|
|
1153
|
+
if target["graph_id"] not in chosen:
|
|
1154
|
+
report["links_unresolved"].append(
|
|
1155
|
+
f"{where}: the graph '{target['graph_id']}' is not merged")
|
|
1156
|
+
continue
|
|
1157
|
+
if link["source"] not in nodes or target["node_id"] not in nodes:
|
|
1158
|
+
missing = (link["source"] if link["source"] not in nodes
|
|
1159
|
+
else target["node_id"])
|
|
1160
|
+
report["links_unresolved"].append(f"{where}: no node '{missing}'")
|
|
1161
|
+
continue
|
|
1162
|
+
try:
|
|
1163
|
+
edge = Edge(link["id"], link["source"], target["node_id"],
|
|
1164
|
+
link["edge_type"])
|
|
1165
|
+
except ValueError as exc:
|
|
1166
|
+
report["links_unresolved"].append(f"{where}: {exc}")
|
|
1167
|
+
continue
|
|
1168
|
+
edge.attributes = dict(link.get("attributes") or {})
|
|
1169
|
+
report["edges_in"] += 1
|
|
1170
|
+
report["links_resolved"] += 1
|
|
1171
|
+
take(edge, gid)
|
|
1172
|
+
|
|
1173
|
+
# Graph() makes a geo position of its own; the members bring theirs
|
|
1174
|
+
if any(getattr(n, "node_type", None) == "geo_position" for n in nodes.values()):
|
|
1175
|
+
for node_id in auto_geo:
|
|
1176
|
+
if node_id not in nodes:
|
|
1177
|
+
merged.remove_node(node_id)
|
|
1178
|
+
merged.nodes = list(merged.nodes) + [n for i, n in nodes.items()
|
|
1179
|
+
if merged.find_node_by_id(i) is None]
|
|
1180
|
+
merged.edges = list(edges.values())
|
|
1181
|
+
report["nodes"] = len(nodes)
|
|
1182
|
+
report["edges"] = len(edges)
|
|
1183
|
+
return merged, report
|
|
@@ -474,7 +474,7 @@ def apply_delta(section: Dict[str, Any], descriptor: ConnectorDescriptor,
|
|
|
474
474
|
so a rejected write cannot leave half a subgraph behind.
|
|
475
475
|
"""
|
|
476
476
|
from ..crdt import apply_op_to_section, make_op
|
|
477
|
-
from ..editorial import
|
|
477
|
+
from ..editorial import now_op_iso
|
|
478
478
|
|
|
479
479
|
verdict = guard_write(descriptor, capability, delta,
|
|
480
480
|
node_types={str(n.get("id")): str(n.get("node_type") or "")
|
|
@@ -488,8 +488,9 @@ def apply_delta(section: Dict[str, Any], descriptor: ConnectorDescriptor,
|
|
|
488
488
|
# in `data`) are written by the CRDT only when the op carries a clock —
|
|
489
489
|
# measured: without one, a write landed unattributed even though the author was
|
|
490
490
|
# right there. The identity and the clock are never typed by a caller
|
|
491
|
-
# (`editorial.py`'s rule), so the seam supplies the clock
|
|
492
|
-
|
|
491
|
+
# (`editorial.py`'s rule), so the seam supplies the clock — an operation's,
|
|
492
|
+
# to the millisecond (E.D., 12 Oct 2026); the CRDT keeps the stamps at the second.
|
|
493
|
+
at = at or now_op_iso()
|
|
493
494
|
applied = {"nodes": 0, "edges": 0}
|
|
494
495
|
refused: List[Dict[str, Any]] = []
|
|
495
496
|
|
|
@@ -17,7 +17,10 @@ Three pieces:
|
|
|
17
17
|
(AUDIT1). Comparison is by instant, then by author, lexicographically smaller
|
|
18
18
|
first. The tie-break is arbitrary and DECLARED (``tie-author``); what it must
|
|
19
19
|
never be is "whichever I saw last", because then two people merging the same two
|
|
20
|
-
files get different projects and no way to tell.
|
|
20
|
+
files get different projects and no way to tell. The SAME clock on two different
|
|
21
|
+
values (one hand, one instant: a connector's batch, a burst of renames) is
|
|
22
|
+
settled by the value itself (``tie-value``, :func:`tie_rank`) — measured on 12
|
|
23
|
+
Oct 2026, it used to be settled by arrival, and two copies kept two names.
|
|
21
24
|
|
|
22
25
|
**Tombstones.** A deletion is not an absence, it is a mark: ``data.removed =
|
|
23
26
|
{ts, by}``, inline, keeping the id. Views hide it; the merge SEES it. Without
|
|
@@ -73,7 +76,16 @@ OPS = ("add_node", "update_field", "remove_node", "add_edge", "remove_edge")
|
|
|
73
76
|
#: The incoming value is kept (P3's behaviour) and the reason
|
|
74
77
|
#: exists so nobody reads that as a judgement.
|
|
75
78
|
#: ``resurrected`` — an edit later than a deletion brought the node back.
|
|
76
|
-
|
|
79
|
+
#: ``tie-explicit``— same instant, same author, and only ONE side carries the
|
|
80
|
+
#: field's own clock (the other is dated by its node's stamp):
|
|
81
|
+
#: the field's own clock wins — a field is written on a node
|
|
82
|
+
#: that is already there.
|
|
83
|
+
#: ``tie-value`` — same instant, same author, both clocks the field's own, two
|
|
84
|
+
#: different values: the greater :func:`tie_rank` wins. Not a
|
|
85
|
+
#: judgement — the one choice every copy makes whatever order
|
|
86
|
+
#: the two arrive in.
|
|
87
|
+
FIELD_REASONS = ("newer", "tie-author", "unstamped", "resurrected",
|
|
88
|
+
"tie-explicit", "tie-value")
|
|
77
89
|
|
|
78
90
|
|
|
79
91
|
# ── clocks ───────────────────────────────────────────────────────────────────
|
|
@@ -157,13 +169,35 @@ def compare_clocks(a: Clock, b: Clock) -> Tuple[int, str]:
|
|
|
157
169
|
return (1, "tie-author") if ka < kb else (-1, "tie-author")
|
|
158
170
|
|
|
159
171
|
|
|
172
|
+
def editorial_clock(clock: Clock) -> Clock:
|
|
173
|
+
"""The clock as an EDITORIAL stamp records it: at the second.
|
|
174
|
+
|
|
175
|
+
Two precisions, one decision (E.D., 12 Oct 2026): the clock of an operation
|
|
176
|
+
(``op.ts``, ``field_clocks``, tombstones) is to the millisecond, because it
|
|
177
|
+
orders two hands; ``created_at`` / ``modified_at`` stay at the second
|
|
178
|
+
(:func:`s3dgraphy.editorial.now_iso`). Every stamp the CRDT writes from an
|
|
179
|
+
op's clock goes through here, and is compared at the second too — so two
|
|
180
|
+
hands in one second settle the stamp by the declared ``tie-author``, not by
|
|
181
|
+
arrival."""
|
|
182
|
+
if not clock.stamped:
|
|
183
|
+
return clock
|
|
184
|
+
from .editorial import normalize_instant
|
|
185
|
+
return Clock(ts=normalize_instant(clock.ts), by=clock.by)
|
|
186
|
+
|
|
187
|
+
|
|
160
188
|
def clock_order(a: Clock, b: Clock) -> int:
|
|
161
189
|
"""Just the ordering of two clocks (-1 / 0 / 1), without the reason."""
|
|
162
190
|
return compare_clocks(a, b)[0]
|
|
163
191
|
|
|
164
192
|
|
|
165
193
|
def newer(a: Clock, b: Clock) -> Clock:
|
|
166
|
-
|
|
194
|
+
order = clock_order(a, b)
|
|
195
|
+
if order == 0:
|
|
196
|
+
# the same instant may be spelt two ways ("…:00Z", "…:00.000Z": a clock
|
|
197
|
+
# at the second and one at the millisecond): ONE spelling, whichever
|
|
198
|
+
# side is asked, or two copies differ by bytes nobody wrote
|
|
199
|
+
return a if (a.ts or "", a.by or "") >= (b.ts or "", b.by or "") else b
|
|
200
|
+
return a if order > 0 else b
|
|
167
201
|
|
|
168
202
|
|
|
169
203
|
# ── reading a payload ────────────────────────────────────────────────────────
|
|
@@ -210,14 +244,17 @@ def field_clock(payload: Dict[str, Any], field_name: str) -> Clock:
|
|
|
210
244
|
"""
|
|
211
245
|
data = payload.get("data") if isinstance(payload.get("data"), dict) else {}
|
|
212
246
|
clocks = data.get(FIELD_CLOCKS_KEY)
|
|
247
|
+
# the two fallbacks are editorial stamps, so they are read at the second
|
|
248
|
+
# (`editorial_clock`) — as the CRDT writes them since 12 Oct 2026, and also
|
|
249
|
+
# when an older tool wrote one with its milliseconds
|
|
213
250
|
if isinstance(clocks, dict):
|
|
214
251
|
if field_name in clocks:
|
|
215
252
|
return Clock.from_dict(clocks[field_name])
|
|
216
253
|
if clocks:
|
|
217
254
|
born = creation_stamp(payload)
|
|
218
255
|
if born.stamped:
|
|
219
|
-
return born
|
|
220
|
-
return node_stamp(payload)
|
|
256
|
+
return editorial_clock(born)
|
|
257
|
+
return editorial_clock(node_stamp(payload))
|
|
221
258
|
|
|
222
259
|
|
|
223
260
|
def is_stale_copy(payload: Dict[str, Any], field_name: str) -> bool:
|
|
@@ -444,6 +481,32 @@ def canonical(value: Any) -> str:
|
|
|
444
481
|
ensure_ascii=False, default=str)
|
|
445
482
|
|
|
446
483
|
|
|
484
|
+
def tie_rank(value: Any, removed: bool = False) -> Tuple[int, bytes]:
|
|
485
|
+
"""Where a field's state stands when two states carry the SAME clock.
|
|
486
|
+
|
|
487
|
+
The rule of ``tie-value``: the greater rank wins. An emptying ranks BELOW
|
|
488
|
+
every value (at the same instant a value is kept rather than lost); values
|
|
489
|
+
rank by the UTF-8 bytes of their :func:`canonical` JSON, which is code-point
|
|
490
|
+
order. A twin in another language must compare code points too — not
|
|
491
|
+
UTF-16 units, which order an emoji before ``"\\uffff"``."""
|
|
492
|
+
if removed:
|
|
493
|
+
return (0, b"")
|
|
494
|
+
return (1, canonical(value).encode("utf-8"))
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _settle_tie(mine: Dict[str, Any], theirs: Dict[str, Any], name: str,
|
|
498
|
+
v_mine: Any, v_theirs: Any, mine_gone: bool,
|
|
499
|
+
theirs_gone: bool) -> Tuple[str, str]:
|
|
500
|
+
"""``(winning side, reason)`` for two different states of one field under
|
|
501
|
+
the SAME clock (instant and author): ``tie-explicit``, else ``tie-value``."""
|
|
502
|
+
explicit_mine = clock_source(mine, name) == "field_clock"
|
|
503
|
+
explicit_theirs = clock_source(theirs, name) == "field_clock"
|
|
504
|
+
if explicit_mine != explicit_theirs:
|
|
505
|
+
return ("mine" if explicit_mine else "theirs"), "tie-explicit"
|
|
506
|
+
return ("mine" if tie_rank(v_mine, mine_gone) > tie_rank(v_theirs, theirs_gone)
|
|
507
|
+
else "theirs"), "tie-value"
|
|
508
|
+
|
|
509
|
+
|
|
447
510
|
# ── the report ───────────────────────────────────────────────────────────────
|
|
448
511
|
|
|
449
512
|
@dataclass
|
|
@@ -501,11 +564,9 @@ def merge_payloads(mine: Dict[str, Any], theirs: Dict[str, Any]) -> MergeOutcome
|
|
|
501
564
|
"id": node_id,
|
|
502
565
|
# identity is not a register: a type is decided when the node is made.
|
|
503
566
|
# If the two disagree, the newer node stamp decides — and nothing else in
|
|
504
|
-
# this module lets identity race.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
else mine.get("node_type")) or mine.get("node_type")
|
|
508
|
-
or theirs.get("node_type"),
|
|
567
|
+
# this module lets identity race. Under the same stamp the greater type
|
|
568
|
+
# name decides, so that the answer does not depend on which side is mine.
|
|
569
|
+
"node_type": _merge_type(mine, theirs),
|
|
509
570
|
}
|
|
510
571
|
outcome = MergeOutcome(payload=merged)
|
|
511
572
|
|
|
@@ -558,7 +619,12 @@ def merge_payloads(mine: Dict[str, Any], theirs: Dict[str, Any]) -> MergeOutcome
|
|
|
558
619
|
# the date did not decide: the incoming state is kept, as it always
|
|
559
620
|
# was, and the reason says the choice was not a judgement
|
|
560
621
|
win_side = "theirs"
|
|
561
|
-
elif order
|
|
622
|
+
elif order == 0:
|
|
623
|
+
# the SAME clock on two different states: the state decides, so
|
|
624
|
+
# that the result does not depend on which side is `mine`
|
|
625
|
+
win_side, reason = _settle_tie(mine, theirs, name, v_mine, v_theirs,
|
|
626
|
+
mine_gone, theirs_gone)
|
|
627
|
+
elif order > 0:
|
|
562
628
|
win_side = "mine"
|
|
563
629
|
else:
|
|
564
630
|
win_side = "theirs"
|
|
@@ -611,7 +677,8 @@ def merge_payloads(mine: Dict[str, Any], theirs: Dict[str, Any]) -> MergeOutcome
|
|
|
611
677
|
_merge_creation(merged, mine, theirs)
|
|
612
678
|
last = Clock()
|
|
613
679
|
for clock in list(winning_clocks.values()) + [node_stamp(mine), node_stamp(theirs)]:
|
|
614
|
-
|
|
680
|
+
# at the second, like every stamp an op leaves (`_stamp_payload`)
|
|
681
|
+
last = newer(last, editorial_clock(clock))
|
|
615
682
|
if last.stamped:
|
|
616
683
|
data = merged.setdefault("data", {})
|
|
617
684
|
data["modified_at"] = last.ts
|
|
@@ -645,6 +712,16 @@ def merge_payloads(mine: Dict[str, Any], theirs: Dict[str, Any]) -> MergeOutcome
|
|
|
645
712
|
return outcome
|
|
646
713
|
|
|
647
714
|
|
|
715
|
+
def _merge_type(mine: Dict[str, Any], theirs: Dict[str, Any]) -> Any:
|
|
716
|
+
a, b = mine.get("node_type"), theirs.get("node_type")
|
|
717
|
+
if not a or not b:
|
|
718
|
+
return a or b
|
|
719
|
+
order = clock_order(node_stamp(theirs), node_stamp(mine))
|
|
720
|
+
if order == 0:
|
|
721
|
+
return max(str(a), str(b))
|
|
722
|
+
return b if order > 0 else a
|
|
723
|
+
|
|
724
|
+
|
|
648
725
|
def _merge_creation(merged: Dict[str, Any], mine: Dict[str, Any],
|
|
649
726
|
theirs: Dict[str, Any]) -> None:
|
|
650
727
|
def creation(payload: Dict[str, Any]) -> Clock:
|
|
@@ -656,7 +733,14 @@ def _merge_creation(merged: Dict[str, Any], mine: Dict[str, Any],
|
|
|
656
733
|
a, b = creation(mine), creation(theirs)
|
|
657
734
|
if not a.stamped and not b.stamped:
|
|
658
735
|
return
|
|
659
|
-
|
|
736
|
+
if not b.stamped:
|
|
737
|
+
first = a
|
|
738
|
+
elif not a.stamped:
|
|
739
|
+
first = b
|
|
740
|
+
else:
|
|
741
|
+
order = clock_order(a, b)
|
|
742
|
+
# the earlier creation; under one clock, the one spelling `newer` picks
|
|
743
|
+
first = newer(a, b) if order == 0 else (a if order < 0 else b)
|
|
660
744
|
data = merged.setdefault("data", {})
|
|
661
745
|
data["created_at"] = first.ts
|
|
662
746
|
if first.by:
|
|
@@ -1160,12 +1244,49 @@ def apply_op_to_section(section: Dict[str, Any], op: Dict[str, Any], *,
|
|
|
1160
1244
|
wants_gone = op.get("remove") is True
|
|
1161
1245
|
same_value = (gone == wants_gone
|
|
1162
1246
|
and canonical(get_field(existing, name)) == canonical(op.get("value")))
|
|
1247
|
+
explicit = clock_source(existing, name) == "field_clock"
|
|
1248
|
+
if order == 0 and same_value and reason == "tie-author" and (
|
|
1249
|
+
not explicit or (newer(clock, current) is clock and clock.ts != current.ts)):
|
|
1250
|
+
# the same value under the same clock: no content moves, but the
|
|
1251
|
+
# field takes its OWN clock — against the node-stamp fallback it is
|
|
1252
|
+
# still a write, and without the record an emptying under the same
|
|
1253
|
+
# clock would win or lose by arrival (measured, 45 pairs in 20000);
|
|
1254
|
+
# or the same instant spelt otherwise ("…:00Z" and "…:00.000Z"),
|
|
1255
|
+
# where `newer` picks the one spelling
|
|
1256
|
+
set_field_clock(existing, name, clock, removed=gone)
|
|
1163
1257
|
if order < 0 or (order == 0 and same_value):
|
|
1164
|
-
# the state is newer (or this is the same op again): nothing moves
|
|
1258
|
+
# the state is newer (or this is the same op again): nothing moves…
|
|
1259
|
+
# but the last-hand stamp sees this op like every other. The stamp is
|
|
1260
|
+
# at the second and the field at the millisecond, so a stale op can
|
|
1261
|
+
# still TIE the stamp — and if only applied ops counted, who is
|
|
1262
|
+
# the last hand of that second would depend on the arrival (measured,
|
|
1263
|
+
# 348 pairs in 20000). Counted always, the stamp is the max of all.
|
|
1264
|
+
_stamp_payload(existing, clock, creation=False, auth=_op_auth(op)[0])
|
|
1165
1265
|
return OpResult(False, "stale" if order < 0 else "idempotent", node_id)
|
|
1166
1266
|
if order == 0 and not same_value and reason == "unstamped":
|
|
1167
1267
|
# no clocks anywhere: the arriving value is taken, and declared
|
|
1168
1268
|
pass
|
|
1269
|
+
if order == 0 and reason == "tie-author":
|
|
1270
|
+
# the SAME clock (instant and author) on a different state. Against
|
|
1271
|
+
# a node-stamp fallback the op's own clock wins (`tie-explicit`);
|
|
1272
|
+
# against the field's own clock the state decides (`tie-value`),
|
|
1273
|
+
# never the arrival — measured on 12 Oct 2026, a burst of renames in
|
|
1274
|
+
# one millisecond left the room on the last and EMStudio on the first
|
|
1275
|
+
if not explicit:
|
|
1276
|
+
reason = "tie-explicit"
|
|
1277
|
+
elif tie_rank(op.get("value"), wants_gone) < tie_rank(get_field(existing, name), gone):
|
|
1278
|
+
# the value stays; the node's last-hand stamp still sees this
|
|
1279
|
+
# instant, so its spelling does not depend on which op won
|
|
1280
|
+
_stamp_payload(existing, clock, creation=False, auth=_op_auth(op)[0])
|
|
1281
|
+
return OpResult(False, "tie-value", node_id, [FieldOutcome(
|
|
1282
|
+
node_id=node_id, field=name, reason="tie-value",
|
|
1283
|
+
winner={"by": current.by, "at": current.ts, "side": "state",
|
|
1284
|
+
"removed": gone},
|
|
1285
|
+
loser={"by": clock.by, "at": clock.ts, "side": "op",
|
|
1286
|
+
"removed": wants_gone},
|
|
1287
|
+
loser_value=None if wants_gone else op.get("value"))])
|
|
1288
|
+
else:
|
|
1289
|
+
reason = "tie-value"
|
|
1169
1290
|
loser_value = get_field(existing, name)
|
|
1170
1291
|
# ONE act, the same one `api.set_field` performs: a value with its clock,
|
|
1171
1292
|
# or an emptying with its tombstone. `remove: true` (or a null value with
|
|
@@ -1219,9 +1340,12 @@ def apply_op_to_section(section: Dict[str, Any], op: Dict[str, Any], *,
|
|
|
1219
1340
|
learned = _merge_declared(attrs, declared)
|
|
1220
1341
|
# the relation was created by its OLDEST add, whichever arrives
|
|
1221
1342
|
# first: without this two adds converge only in one order
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1343
|
+
# (a stamp, so at the second: `editorial_clock`)
|
|
1344
|
+
born = editorial_clock(Clock(ts=attrs.get("created_at"),
|
|
1345
|
+
by=attrs.get("created_by")))
|
|
1346
|
+
stamp = editorial_clock(clock)
|
|
1347
|
+
if stamp.stamped and (not born.stamped or clock_order(stamp, born) < 0):
|
|
1348
|
+
attrs.update({"created_at": stamp.ts, "created_by": stamp.by})
|
|
1225
1349
|
learned = True
|
|
1226
1350
|
mark = Clock.from_dict(attrs.get(REMOVED_KEY))
|
|
1227
1351
|
if mark.stamped and clock_order(clock, mark) > 0:
|
|
@@ -1234,7 +1358,8 @@ def apply_op_to_section(section: Dict[str, Any], op: Dict[str, Any], *,
|
|
|
1234
1358
|
else OpResult(False, "idempotent"))
|
|
1235
1359
|
attrs = dict(declared)
|
|
1236
1360
|
if clock.stamped:
|
|
1237
|
-
|
|
1361
|
+
stamp = editorial_clock(clock)
|
|
1362
|
+
attrs.update({"created_at": stamp.ts, "created_by": stamp.by})
|
|
1238
1363
|
if attrs:
|
|
1239
1364
|
edge["attributes"] = attrs
|
|
1240
1365
|
edges.append(edge)
|
|
@@ -1317,6 +1442,9 @@ def _stamp_payload(payload: Dict[str, Any], clock: Clock, *, creation: bool,
|
|
|
1317
1442
|
"""
|
|
1318
1443
|
if not clock.stamped:
|
|
1319
1444
|
return
|
|
1445
|
+
# the op's clock is to the millisecond; the stamps it leaves stay at the
|
|
1446
|
+
# second (E.D., 12 Oct 2026), compared as written — at the second
|
|
1447
|
+
clock = editorial_clock(clock)
|
|
1320
1448
|
data = payload.setdefault("data", {})
|
|
1321
1449
|
if creation and not data.get("created_at"):
|
|
1322
1450
|
data["created_at"] = clock.ts
|
|
@@ -1324,8 +1452,8 @@ def _stamp_payload(payload: Dict[str, Any], clock: Clock, *, creation: bool,
|
|
|
1324
1452
|
data["created_by"] = clock.by
|
|
1325
1453
|
if auth:
|
|
1326
1454
|
data["created_auth"] = dict(auth)
|
|
1327
|
-
current = node_stamp(payload)
|
|
1328
|
-
if
|
|
1455
|
+
current = editorial_clock(node_stamp(payload))
|
|
1456
|
+
if newer(clock, current) is clock:
|
|
1329
1457
|
data["modified_at"] = clock.ts
|
|
1330
1458
|
if clock.by:
|
|
1331
1459
|
data["modified_by"] = clock.by
|
|
@@ -1333,6 +1461,12 @@ def _stamp_payload(payload: Dict[str, Any], clock: Clock, *, creation: bool,
|
|
|
1333
1461
|
data["modified_auth"] = dict(auth)
|
|
1334
1462
|
else:
|
|
1335
1463
|
data.pop("modified_auth", None)
|
|
1464
|
+
else:
|
|
1465
|
+
# a later hand nobody named: the previous hand is not the last any
|
|
1466
|
+
# more, and leaving it beside this instant made a clock nobody had
|
|
1467
|
+
# — one that depended on the order (measured, 12 Oct 2026)
|
|
1468
|
+
data.pop("modified_by", None)
|
|
1469
|
+
data.pop("modified_auth", None)
|
|
1336
1470
|
|
|
1337
1471
|
|
|
1338
1472
|
def _op_auth(op: Dict[str, Any]):
|