lamindb 1.10.0__tar.gz → 1.10.2__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.
Files changed (288) hide show
  1. {lamindb-1.10.0 → lamindb-1.10.2}/.github/workflows/build.yml +1 -1
  2. {lamindb-1.10.0 → lamindb-1.10.2}/PKG-INFO +5 -4
  3. {lamindb-1.10.0 → lamindb-1.10.2}/docs/arrays.ipynb +17 -60
  4. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/pydantic-pandera.ipynb +248 -14
  5. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/__init__.py +1 -1
  6. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_settings.py +45 -2
  7. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_anndata_accessor.py +96 -18
  8. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_backed_access.py +10 -7
  9. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_spatialdata_accessor.py +15 -4
  10. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_zarr.py +3 -0
  11. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/curators/core.py +7 -5
  12. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/datasets/__init__.py +4 -1
  13. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/datasets/_core.py +33 -1
  14. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/schemas/_anndata.py +1 -1
  15. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/schemas/_simple.py +1 -1
  16. lamindb-1.10.2/lamindb/migrations/0118_alter_recordproject_value_projectrecord.py +99 -0
  17. lamindb-1.10.2/lamindb/migrations/0119_rename_records_project_linked_in_records.py +26 -0
  18. lamindb-1.10.0/lamindb/migrations/0117_squashed.py → lamindb-1.10.2/lamindb/migrations/0119_squashed.py +87 -3
  19. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/artifact.py +31 -20
  20. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/project.py +24 -2
  21. {lamindb-1.10.0 → lamindb-1.10.2}/noxfile.py +4 -4
  22. {lamindb-1.10.0 → lamindb-1.10.2}/pyproject.toml +2 -2
  23. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_curators_general.py +19 -0
  24. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/scripts/setup_access.py +1 -1
  25. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/conftest.py +3 -4
  26. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_artifact_storage.py +6 -9
  27. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_storage_lifecycle.py +1 -0
  28. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_streaming.py +55 -1
  29. {lamindb-1.10.0 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  30. {lamindb-1.10.0 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  31. {lamindb-1.10.0 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
  32. {lamindb-1.10.0 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/usage_question.yml +0 -0
  33. {lamindb-1.10.0 → lamindb-1.10.2}/.github/workflows/doc-changes.yml +0 -0
  34. {lamindb-1.10.0 → lamindb-1.10.2}/.gitignore +0 -0
  35. {lamindb-1.10.0 → lamindb-1.10.2}/.gitmodules +0 -0
  36. {lamindb-1.10.0 → lamindb-1.10.2}/.pre-commit-config.yaml +0 -0
  37. {lamindb-1.10.0 → lamindb-1.10.2}/CONTRIBUTING.md +0 -0
  38. {lamindb-1.10.0 → lamindb-1.10.2}/LICENSE +0 -0
  39. {lamindb-1.10.0 → lamindb-1.10.2}/README.md +0 -0
  40. {lamindb-1.10.0 → lamindb-1.10.2}/docs/api.md +0 -0
  41. {lamindb-1.10.0 → lamindb-1.10.2}/docs/bio-registries.ipynb +0 -0
  42. {lamindb-1.10.0 → lamindb-1.10.2}/docs/bionty.md +0 -0
  43. {lamindb-1.10.0 → lamindb-1.10.2}/docs/changelog.md +0 -0
  44. {lamindb-1.10.0 → lamindb-1.10.2}/docs/clinicore.md +0 -0
  45. {lamindb-1.10.0 → lamindb-1.10.2}/docs/curate.ipynb +0 -0
  46. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/acid.ipynb +0 -0
  47. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/curate-any.ipynb +0 -0
  48. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/delete.ipynb +0 -0
  49. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/idempotency.ipynb +0 -0
  50. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/import-modules.ipynb +0 -0
  51. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/keep-artifacts-local.ipynb +0 -0
  52. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/reference-field.ipynb +0 -0
  53. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/search.ipynb +0 -0
  54. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/setup.ipynb +0 -0
  55. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/symbol-mapping.ipynb +0 -0
  56. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/test_notebooks.py +0 -0
  57. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/track-run-inputs.ipynb +0 -0
  58. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/validate-fields.ipynb +0 -0
  59. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq/visibility.ipynb +0 -0
  60. {lamindb-1.10.0 → lamindb-1.10.2}/docs/faq.md +0 -0
  61. {lamindb-1.10.0 → lamindb-1.10.2}/docs/guide.md +0 -0
  62. {lamindb-1.10.0 → lamindb-1.10.2}/docs/includes/installation.md +0 -0
  63. {lamindb-1.10.0 → lamindb-1.10.2}/docs/index.md +0 -0
  64. {lamindb-1.10.0 → lamindb-1.10.2}/docs/lamindb.md +0 -0
  65. {lamindb-1.10.0 → lamindb-1.10.2}/docs/query-search.md +0 -0
  66. {lamindb-1.10.0 → lamindb-1.10.2}/docs/registries.ipynb +0 -0
  67. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_anndata_flexible.py +0 -0
  68. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_dataframe_flexible.py +0 -0
  69. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_dataframe_minimal_errors.py +0 -0
  70. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_mudata.py +0 -0
  71. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_soma_experiment.py +0 -0
  72. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/curate_spatialdata.py +0 -0
  73. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/define_mini_immuno_features_labels.py +0 -0
  74. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/define_mini_immuno_schema_flexible.py +0 -0
  75. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/define_schema_anndata_ensembl_gene_ids_and_valid_features_in_obs.py +0 -0
  76. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/define_schema_spatialdata.py +0 -0
  77. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/define_valid_features.py +0 -0
  78. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/run_track_and_finish.py +0 -0
  79. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/run_track_with_params.py +0 -0
  80. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/run_workflow.py +0 -0
  81. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/save_mini_immuno_datasets.py +0 -0
  82. {lamindb-1.10.0 → lamindb-1.10.2}/docs/scripts/synced_with_git.py +0 -0
  83. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/add-replace-cache.ipynb +0 -0
  84. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/anndata-accessor.ipynb +0 -0
  85. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/prepare-transfer-local-to-cloud.ipynb +0 -0
  86. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/test-files/iris.csv +0 -0
  87. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/test-files/iris.data +0 -0
  88. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/test-files/new_iris.csv +0 -0
  89. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/test_notebooks.py +0 -0
  90. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/transfer-local-to-cloud.ipynb +0 -0
  91. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/upload.ipynb +0 -0
  92. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage/vitessce.ipynb +0 -0
  93. {lamindb-1.10.0 → lamindb-1.10.2}/docs/storage.md +0 -0
  94. {lamindb-1.10.0 → lamindb-1.10.2}/docs/test_notebooks.py +0 -0
  95. {lamindb-1.10.0 → lamindb-1.10.2}/docs/track.ipynb +0 -0
  96. {lamindb-1.10.0 → lamindb-1.10.2}/docs/transfer.ipynb +0 -0
  97. {lamindb-1.10.0 → lamindb-1.10.2}/docs/wetlab.md +0 -0
  98. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/_finish.py +0 -0
  99. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/_tracked.py +0 -0
  100. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/_view.py +0 -0
  101. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/__init__.py +0 -0
  102. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/fields.py +0 -0
  103. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/ids.py +0 -0
  104. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/types.py +0 -0
  105. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/uids.py +0 -0
  106. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/base/users.py +0 -0
  107. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/__init__.py +0 -0
  108. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_compat.py +0 -0
  109. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_context.py +0 -0
  110. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_mapped_collection.py +0 -0
  111. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_sync_git.py +0 -0
  112. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/_track_environment.py +0 -0
  113. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/exceptions.py +0 -0
  114. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/loaders.py +0 -0
  115. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/__init__.py +0 -0
  116. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_polars_lazy_df.py +0 -0
  117. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_pyarrow_dataset.py +0 -0
  118. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_tiledbsoma.py +0 -0
  119. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/_valid_suffixes.py +0 -0
  120. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/objects.py +0 -0
  121. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/storage/paths.py +0 -0
  122. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/subsettings/__init__.py +0 -0
  123. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/subsettings/_annotation_settings.py +0 -0
  124. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/subsettings/_creation_settings.py +0 -0
  125. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/core/types.py +0 -0
  126. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/curators/__init__.py +0 -0
  127. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/curators/_legacy.py +0 -0
  128. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/errors.py +0 -0
  129. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/__init__.py +0 -0
  130. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/cellxgene/__init__.py +0 -0
  131. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/cellxgene/_cellxgene.py +0 -0
  132. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/cellxgene/cxg_schema_versions.csv +0 -0
  133. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/croissant/__init__.py +0 -0
  134. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/croissant/mini_immuno.anndata.zarr_metadata.json +0 -0
  135. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/datasets/_fake.py +0 -0
  136. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/datasets/_small.py +0 -0
  137. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/datasets/mini_immuno.py +0 -0
  138. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/fixtures/__init__.py +0 -0
  139. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/fixtures/sheets.py +0 -0
  140. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/examples/schemas/__init__.py +0 -0
  141. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/integrations/__init__.py +0 -0
  142. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/integrations/_croissant.py +0 -0
  143. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/integrations/_vitessce.py +0 -0
  144. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0069_squashed.py +0 -0
  145. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0070_lamindbv1_migrate_data.py +0 -0
  146. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0071_lamindbv1_migrate_schema.py +0 -0
  147. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0072_remove_user__branch_code_remove_user_aux_and_more.py +0 -0
  148. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0073_merge_ourprojects.py +0 -0
  149. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0074_lamindbv1_part4.py +0 -0
  150. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0075_lamindbv1_part5.py +0 -0
  151. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0076_lamindbv1_part6.py +0 -0
  152. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0077_lamindbv1_part6b.py +0 -0
  153. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0078_lamindbv1_part6c.py +0 -0
  154. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0079_alter_rundata_value_json_and_more.py +0 -0
  155. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0080_polish_lamindbv1.py +0 -0
  156. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0081_revert_textfield_collection.py +0 -0
  157. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0082_alter_feature_dtype.py +0 -0
  158. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0083_alter_feature_is_type_alter_flextable_is_type_and_more.py +0 -0
  159. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0084_alter_schemafeature_feature_and_more.py +0 -0
  160. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0085_alter_feature_is_type_alter_flextable_is_type_and_more.py +0 -0
  161. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0086_various.py +0 -0
  162. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0087_rename__schemas_m2m_artifact_feature_sets_and_more.py +0 -0
  163. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0088_schema_components.py +0 -0
  164. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0089_subsequent_runs.py +0 -0
  165. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0090_runproject_project_runs.py +0 -0
  166. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0091_alter_featurevalue_options_alter_space_options_and_more.py +0 -0
  167. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py +0 -0
  168. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0093_alter_schemacomponent_unique_together.py +0 -0
  169. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0094_writeloglock_writelogmigrationstate_and_more.py +0 -0
  170. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0095_remove_rundata_flextable.py +0 -0
  171. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0096_remove_artifact__param_values_and_more.py +0 -0
  172. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0097_remove_schemaparam_param_remove_paramvalue_param_and_more.py +0 -0
  173. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0098_alter_feature_type_alter_project_type_and_more.py +0 -0
  174. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0099_alter_writelog_seqno.py +0 -0
  175. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0100_branch_alter_artifact__branch_code_and_more.py +0 -0
  176. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0101_alter_artifact_hash_alter_feature_name_and_more.py +0 -0
  177. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0102_remove_writelog_branch_code_and_more.py +0 -0
  178. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0103_remove_writelog_migration_state_and_more.py +0 -0
  179. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0104_alter_branch_uid.py +0 -0
  180. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0105_record_unique_name.py +0 -0
  181. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0106_transfer_data_migration.py +0 -0
  182. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0107_add_schema_to_record.py +0 -0
  183. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0108_remove_record_sheet_remove_sheetproject_sheet_and_more.py +0 -0
  184. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0109_record_input_of_runs_alter_record_run_and_more.py +0 -0
  185. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0110_rename_values_artifacts_record_linked_artifacts.py +0 -0
  186. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0111_remove_record__sort_order.py +0 -0
  187. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0112_alter_recordartifact_feature_and_more.py +0 -0
  188. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0113_lower_case_branch_and_space_names.py +0 -0
  189. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0114_alter_run__status_code.py +0 -0
  190. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0115_alter_space_uid.py +0 -0
  191. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0116_remove_artifact_unique_artifact_storage_key_hash_and_more.py +0 -0
  192. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/0117_fix_artifact_storage_hash_unique_constraints.py +0 -0
  193. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/migrations/__init__.py +0 -0
  194. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/__init__.py +0 -0
  195. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_describe.py +0 -0
  196. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_django.py +0 -0
  197. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_feature_manager.py +0 -0
  198. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_from_values.py +0 -0
  199. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_is_versioned.py +0 -0
  200. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_label_manager.py +0 -0
  201. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/_relations.py +0 -0
  202. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/artifact_set.py +0 -0
  203. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/can_curate.py +0 -0
  204. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/collection.py +0 -0
  205. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/feature.py +0 -0
  206. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/has_parents.py +0 -0
  207. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/query_manager.py +0 -0
  208. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/query_set.py +0 -0
  209. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/record.py +0 -0
  210. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/run.py +0 -0
  211. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/save.py +0 -0
  212. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/schema.py +0 -0
  213. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/sqlrecord.py +0 -0
  214. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/storage.py +0 -0
  215. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/transform.py +0 -0
  216. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/models/ulabel.py +0 -0
  217. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/py.typed +0 -0
  218. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/setup/__init__.py +0 -0
  219. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/setup/_switch.py +0 -0
  220. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/setup/core/__init__.py +0 -0
  221. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/setup/errors/__init__.py +0 -0
  222. {lamindb-1.10.0 → lamindb-1.10.2}/lamindb/setup/types/__init__.py +0 -0
  223. {lamindb-1.10.0 → lamindb-1.10.2}/tests/conftest.py +0 -0
  224. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/_dataset_fixtures.py +0 -0
  225. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/conftest.py +0 -0
  226. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/basic-r-notebook.Rmd.cleaned.html +0 -0
  227. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/basic-r-notebook.Rmd.html +0 -0
  228. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/duplicate/with-title-initialized-consecutive-finish.ipynb +0 -0
  229. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/no-title.ipynb +0 -0
  230. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/with-title-initialized-consecutive-finish-not-last-cell.ipynb +0 -0
  231. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/notebooks/with-title-initialized-consecutive-finish.ipynb +0 -0
  232. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/duplicate1/script-to-test-versioning.py +0 -0
  233. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/duplicate2/script-to-test-versioning.py +0 -0
  234. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/duplicate3/script-to-test-versioning.py +0 -0
  235. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/duplicate4/script-to-test-versioning.py +0 -0
  236. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/duplicate5/script-to-test-versioning.py +0 -0
  237. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/script-to-test-filename-change.py +0 -0
  238. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/scripts/script-to-test-versioning.py +0 -0
  239. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_artifact.py +0 -0
  240. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_artifact_folders.py +0 -0
  241. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_can_curate.py +0 -0
  242. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_collection.py +0 -0
  243. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_data.py +0 -0
  244. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_db.py +0 -0
  245. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_delete.py +0 -0
  246. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_describe_and_df_calls.py +0 -0
  247. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_dtype.py +0 -0
  248. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_feature.py +0 -0
  249. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_feature_label_manager.py +0 -0
  250. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_from_values.py +0 -0
  251. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_has_parents.py +0 -0
  252. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_integrity.py +0 -0
  253. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_load.py +0 -0
  254. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_manager.py +0 -0
  255. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_models.py +0 -0
  256. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_notebooks.py +0 -0
  257. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_queryset.py +0 -0
  258. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_record.py +0 -0
  259. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_run.py +0 -0
  260. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_save.py +0 -0
  261. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_schema.py +0 -0
  262. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_search.py +0 -0
  263. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_settings.py +0 -0
  264. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_storage.py +0 -0
  265. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_track.py +0 -0
  266. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_tracked.py +0 -0
  267. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_transform.py +0 -0
  268. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_ulabel.py +0 -0
  269. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_versioning.py +0 -0
  270. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_view.py +0 -0
  271. {lamindb-1.10.0 → lamindb-1.10.2}/tests/core/test_visibility.py +0 -0
  272. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/conftest.py +0 -0
  273. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_cat_managers.py +0 -0
  274. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_curate_from_croissant.py +0 -0
  275. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_curators_examples.py +0 -0
  276. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_curators_multivalue.py +0 -0
  277. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_cxg_curator.py +0 -0
  278. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_dataframe_curators_accounting_example.py +0 -0
  279. {lamindb-1.10.0 → lamindb-1.10.2}/tests/curators/test_records.py +0 -0
  280. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/conftest.py +0 -0
  281. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/jwt_utils.py +0 -0
  282. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/scripts/check_lamin_dev.py +0 -0
  283. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/scripts/clean_lamin_dev.py +0 -0
  284. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/scripts/setup_instance.py +0 -0
  285. {lamindb-1.10.0 → lamindb-1.10.2}/tests/permissions/test_permissions.py +0 -0
  286. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_artifact_zarr.py +0 -0
  287. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_cache.py +0 -0
  288. {lamindb-1.10.0 → lamindb-1.10.2}/tests/storage/test_transfer.py +0 -0
@@ -69,7 +69,7 @@ jobs:
69
69
  - uses: actions/setup-python@v5
70
70
  with:
71
71
  python-version: |
72
- ${{ github.ref == 'refs/heads/release' && '3.10' ||
72
+ ${{ github.ref == 'refs/heads/release' && '3.11' ||
73
73
  '3.13'
74
74
  }}
75
75
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: lamindb
3
- Version: 1.10.0
3
+ Version: 1.10.2
4
4
  Summary: A data framework for biology.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Requires-Python: >=3.10,<3.14
@@ -9,9 +9,10 @@ Classifier: Programming Language :: Python :: 3.10
9
9
  Classifier: Programming Language :: Python :: 3.11
10
10
  Classifier: Programming Language :: Python :: 3.12
11
11
  Classifier: Programming Language :: Python :: 3.13
12
+ License-File: LICENSE
12
13
  Requires-Dist: lamin_utils==0.15.0
13
14
  Requires-Dist: lamin_cli==1.6.1
14
- Requires-Dist: lamindb_setup[aws]==1.9.0
15
+ Requires-Dist: lamindb_setup[aws]==1.9.1
15
16
  Requires-Dist: pyyaml
16
17
  Requires-Dist: pyarrow
17
18
  Requires-Dist: pandera>=0.24.0
@@ -19,7 +20,7 @@ Requires-Dist: typing_extensions!=4.6.0
19
20
  Requires-Dist: python-dateutil
20
21
  Requires-Dist: pandas>=2.0.0
21
22
  Requires-Dist: scipy<1.15.0
22
- Requires-Dist: anndata>=0.8.0,<=0.12.0
23
+ Requires-Dist: anndata>=0.8.0,<=0.12.1
23
24
  Requires-Dist: fsspec
24
25
  Requires-Dist: graphviz
25
26
  Requires-Dist: psycopg2-binary
@@ -102,62 +102,6 @@
102
102
  "ln.Artifact(\"s3://lamindb-ci/test-arrays/testfile.hdf5\").save()"
103
103
  ]
104
104
  },
105
- {
106
- "cell_type": "markdown",
107
- "metadata": {},
108
- "source": [
109
- "Note that it is also possible to register Hugging Face paths. For this `huggingface_hub` package should be installed."
110
- ]
111
- },
112
- {
113
- "cell_type": "markdown",
114
- "metadata": {},
115
- "source": [
116
- "We register a folder of `parquet` files as a single artifact."
117
- ]
118
- },
119
- {
120
- "cell_type": "code",
121
- "execution_count": null,
122
- "metadata": {
123
- "tags": [
124
- "hide-output"
125
- ]
126
- },
127
- "outputs": [],
128
- "source": [
129
- "ln.Artifact(\"hf://datasets/Koncopd/lamindb-test/sharded_parquet\").save()"
130
- ]
131
- },
132
- {
133
- "cell_type": "markdown",
134
- "metadata": {},
135
- "source": [
136
- "We also register a collection of individual `parquet` files."
137
- ]
138
- },
139
- {
140
- "cell_type": "code",
141
- "execution_count": null,
142
- "metadata": {
143
- "tags": [
144
- "hide-output"
145
- ]
146
- },
147
- "outputs": [],
148
- "source": [
149
- "artifact_shard1 = ln.Artifact(\n",
150
- " \"hf://datasets/Koncopd/lamindb-test/sharded_parquet/louvain=0/947eee0b064440c9b9910ca2eb89e608-0.parquet\"\n",
151
- ").save()\n",
152
- "artifact_shard2 = ln.Artifact(\n",
153
- " \"hf://datasets/Koncopd/lamindb-test/sharded_parquet/louvain=1/947eee0b064440c9b9910ca2eb89e608-0.parquet\"\n",
154
- ").save()\n",
155
- "\n",
156
- "ln.Collection(\n",
157
- " [artifact_shard1, artifact_shard2], key=\"sharded_parquet_collection\"\n",
158
- ").save()"
159
- ]
160
- },
161
105
  {
162
106
  "cell_type": "markdown",
163
107
  "metadata": {},
@@ -495,13 +439,20 @@
495
439
  "A dataframe stored as sharded `parquet`."
496
440
  ]
497
441
  },
442
+ {
443
+ "cell_type": "markdown",
444
+ "metadata": {},
445
+ "source": [
446
+ "Note that it is also possible to register and access Hugging Face paths. For this `huggingface_hub` package should be installed."
447
+ ]
448
+ },
498
449
  {
499
450
  "cell_type": "code",
500
451
  "execution_count": null,
501
452
  "metadata": {},
502
453
  "outputs": [],
503
454
  "source": [
504
- "artifact = ln.Artifact.get(key=\"sharded_parquet\")"
455
+ "artifact = ln.Artifact.using(\"laminlabs/lamindata\").get(key=\"sharded_parquet\")"
505
456
  ]
506
457
  },
507
458
  {
@@ -572,13 +523,19 @@
572
523
  "metadata": {},
573
524
  "outputs": [],
574
525
  "source": [
575
- "collection = ln.Collection.get(key=\"sharded_parquet_collection\")"
526
+ "collection = ln.Collection.using(\"laminlabs/lamindata\").get(\n",
527
+ " key=\"sharded_parquet_collection\"\n",
528
+ ")"
576
529
  ]
577
530
  },
578
531
  {
579
532
  "cell_type": "code",
580
533
  "execution_count": null,
581
- "metadata": {},
534
+ "metadata": {
535
+ "tags": [
536
+ "hide-output"
537
+ ]
538
+ },
582
539
  "outputs": [],
583
540
  "source": [
584
541
  "backed = collection.open()"
@@ -663,7 +620,7 @@
663
620
  "outputs": [],
664
621
  "source": [
665
622
  "# clean up test instance\n",
666
- "!lamin delete --force test-arrays"
623
+ "ln.setup.delete(\"test-arrays\", force=True)"
667
624
  ]
668
625
  }
669
626
  ],
@@ -11,7 +11,7 @@
11
11
  "cell_type": "markdown",
12
12
  "metadata": {},
13
13
  "source": [
14
- "This doc explains conceptual differences between data validation with `pydantic`, `pandera`, and `lamindb`."
14
+ "This doc explains conceptual differences between data validation with `pydantic`, `pandera`, and `LaminDB`."
15
15
  ]
16
16
  },
17
17
  {
@@ -42,10 +42,12 @@
42
42
  "source": [
43
43
  "import pandas as pd\n",
44
44
  "import pydantic\n",
45
- "from typing import Literal\n",
46
45
  "import lamindb as ln\n",
47
46
  "import bionty as bt\n",
48
- "import pandera\n",
47
+ "import pandera.pandas as pandera\n",
48
+ "import pprint\n",
49
+ "\n",
50
+ "from typing import Literal, Any\n",
49
51
  "\n",
50
52
  "df = ln.core.datasets.small_dataset1()\n",
51
53
  "df"
@@ -102,7 +104,6 @@
102
104
  "metadata": {},
103
105
  "outputs": [],
104
106
  "source": [
105
- "# Define the Pandera schema using DataFrameSchema\n",
106
107
  "pandera_schema = pandera.DataFrameSchema(\n",
107
108
  " {\n",
108
109
  " \"perturbation\": pandera.Column(\n",
@@ -127,14 +128,15 @@
127
128
  "cell_type": "markdown",
128
129
  "metadata": {},
129
130
  "source": [
130
- "### lamindb"
131
+ "### LaminDB"
131
132
  ]
132
133
  },
133
134
  {
134
135
  "cell_type": "markdown",
135
136
  "metadata": {},
136
137
  "source": [
137
- "Features & labels are defined on the level of the database instance. You can either define a schema with required (and optional) columns."
138
+ "Features & labels are defined on the level of the database instance.\n",
139
+ "You can either define a schema with required (and optional) columns."
138
140
  ]
139
141
  },
140
142
  {
@@ -147,8 +149,8 @@
147
149
  },
148
150
  "outputs": [],
149
151
  "source": [
150
- "ln.ULabel(name=\"DMSO\").save() # define a DMSO label\n",
151
- "ln.ULabel(name=\"IFNG\").save() # define an IFNG label\n",
152
+ "ln.ULabel(name=\"DMSO\").save()\n",
153
+ "ln.ULabel(name=\"IFNG\").save()\n",
152
154
  "\n",
153
155
  "# leverage ontologies through types ln.ULabel, bt.CellType, bt.ExperimentalFactor\n",
154
156
  "lamindb_schema = ln.Schema(\n",
@@ -308,7 +310,7 @@
308
310
  "cell_type": "markdown",
309
311
  "metadata": {},
310
312
  "source": [
311
- "### lamindb"
313
+ "### LaminDB"
312
314
  ]
313
315
  },
314
316
  {
@@ -317,7 +319,8 @@
317
319
  "source": [
318
320
  "Because the term `\"CD8-positive, alpha-beta T cell\"` is part of the public `CellType` ontology, validation passes the first time.\n",
319
321
  "\n",
320
- "If validation and not passed, we could have resolved the issue simply by adding a new term to the `CellType` registry rather than editing the code. This also puts downstream data scientists into a position to update ontologies."
322
+ "If validation had not passed, we could have resolved the issue simply by adding a new term to the `CellType` registry rather than editing the code.\n",
323
+ "This also puts downstream data scientists into a position to update ontologies."
321
324
  ]
322
325
  },
323
326
  {
@@ -380,7 +383,7 @@
380
383
  "source": [
381
384
  "## Overview of validation properties\n",
382
385
  "\n",
383
- "Importantly, LaminDB offers not only a `DataFrameCurator`, but also a `AnnDataCurator`, `MuDataCurator`, `SpatialDataCurator`, `TiledbsomaCurator`.\n",
386
+ "Importantly, LaminDB offers not only a `DataFrameCurator`, but also a `AnnDataCurator`, `MuDataCurator`, `SpatialDataCurator`, and `TiledbsomaCurator`.\n",
384
387
  "\n",
385
388
  "The below overview only concerns validating dataframes."
386
389
  ]
@@ -464,7 +467,7 @@
464
467
  "cell_type": "markdown",
465
468
  "metadata": {},
466
469
  "source": [
467
- "If you don't expect a need for Curator functionality for updating ontologies and standaridization, you can also use the `Artifact` constructor."
470
+ "If you don't expect a need for Curator functionality for updating ontologies and standardization, you can also use the `Artifact` constructor."
468
471
  ]
469
472
  },
470
473
  {
@@ -561,11 +564,242 @@
561
564
  "source": [
562
565
  "artifact.schema.features.df()"
563
566
  ]
567
+ },
568
+ {
569
+ "cell_type": "markdown",
570
+ "metadata": {},
571
+ "source": [
572
+ "## Nested data with dynamic keys"
573
+ ]
574
+ },
575
+ {
576
+ "cell_type": "markdown",
577
+ "metadata": {},
578
+ "source": [
579
+ "We will now examine another more complex example where data is nested with potentially arbitrary (dynamic) keys.\n",
580
+ "The example is inspired by the [CELLxGENE schema](https://github.com/chanzuckerberg/single-cell-curation/blob/main/schema/6.0.0/schema.md#uns-dataset-metadata) where annotations are stored as dictionaries in the AnnData `.uns` slot."
581
+ ]
582
+ },
583
+ {
584
+ "cell_type": "code",
585
+ "execution_count": null,
586
+ "metadata": {},
587
+ "outputs": [],
588
+ "source": [
589
+ "uns_dict = ln.core.datasets.dict_cxg_uns()\n",
590
+ "pprint.pprint(uns_dict)"
591
+ ]
592
+ },
593
+ {
594
+ "cell_type": "markdown",
595
+ "metadata": {},
596
+ "source": [
597
+ "### pydantic"
598
+ ]
599
+ },
600
+ {
601
+ "cell_type": "markdown",
602
+ "metadata": {},
603
+ "source": [
604
+ "Pydantic is primed to deal with nested data."
605
+ ]
606
+ },
607
+ {
608
+ "cell_type": "code",
609
+ "execution_count": null,
610
+ "metadata": {},
611
+ "outputs": [],
612
+ "source": [
613
+ "class Images(pydantic.BaseModel):\n",
614
+ " fullres: str\n",
615
+ " hires: str\n",
616
+ "\n",
617
+ "\n",
618
+ "class Scalefactors(pydantic.BaseModel):\n",
619
+ " spot_diameter_fullres: float\n",
620
+ " tissue_hires_scalef: float\n",
621
+ "\n",
622
+ "\n",
623
+ "class Library(pydantic.BaseModel):\n",
624
+ " images: Images\n",
625
+ " scalefactors: Scalefactors\n",
626
+ "\n",
627
+ "\n",
628
+ "class Spatial(pydantic.BaseModel):\n",
629
+ " is_single: bool\n",
630
+ " model_config = {\"extra\": \"allow\"}\n",
631
+ "\n",
632
+ " def __init__(self, **data):\n",
633
+ " libraries = {}\n",
634
+ " other_fields = {}\n",
635
+ "\n",
636
+ " # store all libraries under a single key for validation\n",
637
+ " for key, value in data.items():\n",
638
+ " if key.startswith(\"library_\"):\n",
639
+ " libraries[key] = Library(**value)\n",
640
+ " else:\n",
641
+ " other_fields[key] = value\n",
642
+ "\n",
643
+ " other_fields[\"libraries\"] = libraries\n",
644
+ " super().__init__(**other_fields)\n",
645
+ "\n",
646
+ "\n",
647
+ "class SpatialDataSchema(pydantic.BaseModel):\n",
648
+ " organism_ontology_term_id: str\n",
649
+ " spatial: Spatial\n",
650
+ "\n",
651
+ "\n",
652
+ "validated_data = SpatialDataSchema(**uns_dict)"
653
+ ]
654
+ },
655
+ {
656
+ "cell_type": "markdown",
657
+ "metadata": {},
658
+ "source": [
659
+ "However, pydantic either requires all dictionary keys to be known beforehand to construct the Model classes or workarounds to collect all keys for a single model."
660
+ ]
661
+ },
662
+ {
663
+ "cell_type": "markdown",
664
+ "metadata": {},
665
+ "source": [
666
+ "### pandera"
667
+ ]
668
+ },
669
+ {
670
+ "cell_type": "markdown",
671
+ "metadata": {},
672
+ "source": [
673
+ "Pandera cannot validate dictionaries because it is designed for structured dataframe data.\n",
674
+ "Therefore, we need to flatten the dictionary to transform it into a DataFrame:"
675
+ ]
676
+ },
677
+ {
678
+ "cell_type": "code",
679
+ "execution_count": null,
680
+ "metadata": {},
681
+ "outputs": [],
682
+ "source": [
683
+ "def _flatten_dict(d: dict[Any, Any], parent_key: str = \"\", sep: str = \"_\"):\n",
684
+ " items = []\n",
685
+ " for k, v in d.items():\n",
686
+ " new_key = f\"{parent_key}{sep}{k}\" if parent_key else k\n",
687
+ " if isinstance(v, dict):\n",
688
+ " items.extend(_flatten_dict(v, new_key, sep=sep).items())\n",
689
+ " else:\n",
690
+ " items.append((new_key, v))\n",
691
+ " return dict(items)"
692
+ ]
693
+ },
694
+ {
695
+ "cell_type": "code",
696
+ "execution_count": null,
697
+ "metadata": {},
698
+ "outputs": [],
699
+ "source": [
700
+ "def create_dynamic_schema(flattened_data: dict[str, Any]):\n",
701
+ " schema_dict = {\n",
702
+ " \"organism_ontology_term_id\": pandera.Column(str),\n",
703
+ " \"spatial_is_single\": pandera.Column(bool),\n",
704
+ " }\n",
705
+ "\n",
706
+ " for key in flattened_data.keys():\n",
707
+ " if key.startswith(\"spatial_library_\") and key.endswith(\"_images_fullres\"):\n",
708
+ " lib_prefix = key.replace(\"_images_fullres\", \"\")\n",
709
+ " schema_dict.update(\n",
710
+ " {\n",
711
+ " f\"{lib_prefix}_images_fullres\": pandera.Column(str),\n",
712
+ " f\"{lib_prefix}_images_hires\": pandera.Column(str),\n",
713
+ " f\"{lib_prefix}_scalefactors_spot_diameter_fullres\": pandera.Column(\n",
714
+ " float\n",
715
+ " ),\n",
716
+ " f\"{lib_prefix}_scalefactors_tissue_hires_scalef\": pandera.Column(\n",
717
+ " float\n",
718
+ " ),\n",
719
+ " }\n",
720
+ " )\n",
721
+ "\n",
722
+ " return pandera.DataFrameSchema(schema_dict)\n",
723
+ "\n",
724
+ "\n",
725
+ "flattened = _flatten_dict(uns_dict)\n",
726
+ "df = pd.DataFrame([flattened])\n",
727
+ "spatial_schema = create_dynamic_schema(flattened)\n",
728
+ "validated_df = spatial_schema.validate(df)"
729
+ ]
730
+ },
731
+ {
732
+ "cell_type": "markdown",
733
+ "metadata": {},
734
+ "source": [
735
+ "Analogously to pydantic, pandera does not have out of the box support for dynamically named keys.\n",
736
+ "Therefore, it is necessary to dynamically construct a pydantic schema."
737
+ ]
738
+ },
739
+ {
740
+ "cell_type": "markdown",
741
+ "metadata": {},
742
+ "source": [
743
+ "### LaminDB"
744
+ ]
745
+ },
746
+ {
747
+ "cell_type": "markdown",
748
+ "metadata": {},
749
+ "source": [
750
+ "Similarly, LaminDB currently requires constructing flattened dataframes to dynamically create features for the schema, which can then be used for validation with the DataFrameCurator.\n",
751
+ "Future improvements are expected, including support for a dictionary-specific curator."
752
+ ]
753
+ },
754
+ {
755
+ "cell_type": "code",
756
+ "execution_count": null,
757
+ "metadata": {
758
+ "tags": [
759
+ "hide-output"
760
+ ]
761
+ },
762
+ "outputs": [],
763
+ "source": [
764
+ "def create_dynamic_schema(flattened_data: dict[str, Any]) -> ln.Schema:\n",
765
+ " features = []\n",
766
+ "\n",
767
+ " for key, value in flattened_data.items():\n",
768
+ " if key == \"organism_ontology_term_id\":\n",
769
+ " features.append(ln.Feature(name=key, dtype=bt.Organism.ontology_id).save())\n",
770
+ " elif isinstance(value, bool):\n",
771
+ " features.append(ln.Feature(name=key, dtype=bool).save())\n",
772
+ " elif isinstance(value, (int, float)):\n",
773
+ " features.append(ln.Feature(name=key, dtype=float).save())\n",
774
+ " else:\n",
775
+ " features.append(ln.Feature(name=key, dtype=str).save())\n",
776
+ "\n",
777
+ " return ln.Schema(\n",
778
+ " name=\"Spatial data schema\", features=features, coerce_dtype=True\n",
779
+ " ).save()\n",
780
+ "\n",
781
+ "\n",
782
+ "flattened = _flatten_dict(uns_dict)\n",
783
+ "flattened_df = pd.DataFrame([flattened])\n",
784
+ "spatial_schema = create_dynamic_schema(flattened)\n",
785
+ "curator = ln.curators.DataFrameCurator(flattened_df, spatial_schema)\n",
786
+ "curator.validate()"
787
+ ]
788
+ },
789
+ {
790
+ "cell_type": "markdown",
791
+ "metadata": {},
792
+ "source": [
793
+ "```{note}\n",
794
+ "Curators for scverse data structures allow for the specification of schema slots that access and validate dataframes in nested dictionary attributes like `.attrs` or `.uns`.\n",
795
+ "These schema slots use colon-separated paths like `'attrs:sample'` or `'uns:spatial:images'` to to target specific dataframes for validation.\n",
796
+ "```"
797
+ ]
564
798
  }
565
799
  ],
566
800
  "metadata": {
567
801
  "kernelspec": {
568
- "display_name": "py311",
802
+ "display_name": "lamindb",
569
803
  "language": "python",
570
804
  "name": "python3"
571
805
  },
@@ -579,7 +813,7 @@
579
813
  "name": "python",
580
814
  "nbconvert_exporter": "python",
581
815
  "pygments_lexer": "ipython3",
582
- "version": "3.11.11"
816
+ "version": "3.12.8"
583
817
  }
584
818
  },
585
819
  "nbformat": 4,
@@ -108,7 +108,7 @@ Backwards compatibility.
108
108
 
109
109
  # ruff: noqa: I001
110
110
  # denote a release candidate for 0.1.0 with 0.1rc1, 0.1a1, 0.1b1, etc.
111
- __version__ = "1.10.0"
111
+ __version__ = "1.10.2"
112
112
 
113
113
  import warnings
114
114
 
@@ -10,6 +10,7 @@ from lamindb_setup import settings as setup_settings
10
10
  from lamindb_setup._set_managed_storage import set_managed_storage
11
11
  from lamindb_setup.core import deprecated
12
12
  from lamindb_setup.core._settings_instance import sanitize_git_repo_url
13
+ from lamindb_setup.core._settings_storage import StorageSettings
13
14
 
14
15
  from .subsettings._annotation_settings import AnnotationSettings, annotation_settings
15
16
  from .subsettings._creation_settings import CreationSettings, creation_settings
@@ -18,7 +19,6 @@ if TYPE_CHECKING:
18
19
  from collections.abc import Mapping
19
20
  from pathlib import Path
20
21
 
21
- from lamindb_setup.core._settings_storage import StorageSettings
22
22
  from upath import UPath
23
23
 
24
24
 
@@ -193,13 +193,39 @@ class Settings:
193
193
 
194
194
  @storage.setter
195
195
  def storage(self, path_kwargs: str | Path | UPath | tuple[str | UPath, Mapping]):
196
+ import lamindb as ln
197
+
196
198
  if isinstance(path_kwargs, tuple):
197
199
  path, kwargs = path_kwargs
200
+ # we should ultimately deprecate passing host here, I think
198
201
  if isinstance(kwargs, str):
199
202
  kwargs = {"host": kwargs}
200
203
  else:
201
204
  path, kwargs = path_kwargs, {}
202
- set_managed_storage(path, **kwargs)
205
+ ssettings = StorageSettings(root=path) # there is no need to pass kwargs here!
206
+ exists = ln.Storage.filter(root=ssettings.root_as_str).one_or_none()
207
+ if exists is None:
208
+ response = input(
209
+ f"Storage location {ssettings.root_as_str} does not yet exist. Do you want to continue with creating it? (y/n)"
210
+ )
211
+ # logger.warning(f"deprecated call because storage location does **not yet** exist; going forward, please create through ln.Storage(root={path}).save() going forward")
212
+ if response != "y":
213
+ return None
214
+ set_managed_storage(path, **kwargs)
215
+ else:
216
+ if exists.instance_uid != ln_setup.settings.instance.uid:
217
+ raise ValueError(
218
+ f"Storage {ssettings.root_as_str} exists in another instance ({exists.instance_uid}), cannot write to it from here."
219
+ )
220
+ ssettings = StorageSettings(
221
+ root=exists.root,
222
+ region=exists.region,
223
+ uid=exists.uid,
224
+ instance_id=ln_setup.settings.instance._id,
225
+ )
226
+ ln_setup.settings.instance._storage = ssettings
227
+ kwargs.pop("host", None) # host is not needed for existing storage
228
+ settings.storage._set_fs_kwargs(**kwargs)
203
229
 
204
230
  @property
205
231
  def instance_uid(self) -> str:
@@ -223,6 +249,23 @@ class Settings:
223
249
 
224
250
  @local_storage.setter
225
251
  def local_storage(self, local_root: Path):
252
+ import lamindb as ln
253
+
254
+ # note duplication with storage setter!
255
+ ssettings = StorageSettings(root=local_root)
256
+ exists = ln.Storage.filter(root=ssettings.root_as_str).one_or_none()
257
+ if exists is None:
258
+ response = input(
259
+ f"Storage location {ssettings.root_as_str} does not yet exist. Do you want to continue with creating it? (y/n)"
260
+ )
261
+ # logger.warning(f"deprecated call because storage location does **not yet** exist; going forward, please create through ln.Storage(root={path}).save() going forward")
262
+ if response != "y":
263
+ return None
264
+ else:
265
+ if exists.instance_uid != ln_setup.settings.instance.uid:
266
+ raise ValueError(
267
+ f"Storage {ssettings.root_as_str} exists in another instance ({exists.instance_uid}), cannot write to it from here."
268
+ )
226
269
  ln_setup.settings.instance.local_storage = local_root
227
270
 
228
271
  @property