lamindb 1.10.1__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.
- {lamindb-1.10.1 → lamindb-1.10.2}/PKG-INFO +3 -2
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/__init__.py +1 -1
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_settings.py +45 -2
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_anndata_accessor.py +90 -18
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_backed_access.py +10 -7
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_spatialdata_accessor.py +15 -4
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_zarr.py +3 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/curators/core.py +7 -5
- lamindb-1.10.2/lamindb/migrations/0118_alter_recordproject_value_projectrecord.py +99 -0
- lamindb-1.10.2/lamindb/migrations/0119_rename_records_project_linked_in_records.py +26 -0
- lamindb-1.10.1/lamindb/migrations/0117_squashed.py → lamindb-1.10.2/lamindb/migrations/0119_squashed.py +87 -3
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/artifact.py +31 -20
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/project.py +24 -2
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_curators_general.py +19 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/conftest.py +3 -4
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_artifact_storage.py +6 -9
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_storage_lifecycle.py +1 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_streaming.py +45 -1
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/ISSUE_TEMPLATE/usage_question.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/workflows/build.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.github/workflows/doc-changes.yml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.gitignore +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.gitmodules +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/.pre-commit-config.yaml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/CONTRIBUTING.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/LICENSE +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/README.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/api.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/arrays.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/bio-registries.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/bionty.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/changelog.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/clinicore.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/curate.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/acid.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/curate-any.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/delete.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/idempotency.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/import-modules.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/keep-artifacts-local.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/pydantic-pandera.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/reference-field.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/search.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/setup.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/symbol-mapping.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/test_notebooks.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/track-run-inputs.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/validate-fields.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq/visibility.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/faq.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/guide.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/includes/installation.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/index.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/lamindb.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/query-search.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/registries.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_anndata_flexible.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_dataframe_flexible.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_dataframe_minimal_errors.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_mudata.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_soma_experiment.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/curate_spatialdata.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/define_mini_immuno_features_labels.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/define_mini_immuno_schema_flexible.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/define_schema_anndata_ensembl_gene_ids_and_valid_features_in_obs.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/define_schema_spatialdata.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/define_valid_features.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/run_track_and_finish.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/run_track_with_params.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/run_workflow.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/save_mini_immuno_datasets.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/scripts/synced_with_git.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/add-replace-cache.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/anndata-accessor.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/prepare-transfer-local-to-cloud.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/test-files/iris.csv +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/test-files/iris.data +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/test-files/new_iris.csv +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/test_notebooks.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/transfer-local-to-cloud.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/upload.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage/vitessce.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/storage.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/test_notebooks.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/track.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/transfer.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/docs/wetlab.md +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/_finish.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/_tracked.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/_view.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/fields.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/ids.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/types.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/uids.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/base/users.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_compat.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_context.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_mapped_collection.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_sync_git.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/_track_environment.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/exceptions.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/loaders.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_polars_lazy_df.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_pyarrow_dataset.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_tiledbsoma.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/_valid_suffixes.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/objects.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/storage/paths.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/subsettings/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/subsettings/_annotation_settings.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/subsettings/_creation_settings.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/core/types.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/curators/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/curators/_legacy.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/errors.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/cellxgene/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/cellxgene/_cellxgene.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/cellxgene/cxg_schema_versions.csv +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/croissant/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/croissant/mini_immuno.anndata.zarr_metadata.json +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/datasets/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/datasets/_core.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/datasets/_fake.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/datasets/_small.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/datasets/mini_immuno.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/fixtures/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/fixtures/sheets.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/schemas/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/schemas/_anndata.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/examples/schemas/_simple.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/integrations/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/integrations/_croissant.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/integrations/_vitessce.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0069_squashed.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0070_lamindbv1_migrate_data.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0071_lamindbv1_migrate_schema.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0072_remove_user__branch_code_remove_user_aux_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0073_merge_ourprojects.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0074_lamindbv1_part4.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0075_lamindbv1_part5.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0076_lamindbv1_part6.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0077_lamindbv1_part6b.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0078_lamindbv1_part6c.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0079_alter_rundata_value_json_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0080_polish_lamindbv1.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0081_revert_textfield_collection.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0082_alter_feature_dtype.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0083_alter_feature_is_type_alter_flextable_is_type_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0084_alter_schemafeature_feature_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0085_alter_feature_is_type_alter_flextable_is_type_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0086_various.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0087_rename__schemas_m2m_artifact_feature_sets_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0088_schema_components.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0089_subsequent_runs.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0090_runproject_project_runs.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0091_alter_featurevalue_options_alter_space_options_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0092_alter_artifactfeaturevalue_artifact_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0093_alter_schemacomponent_unique_together.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0094_writeloglock_writelogmigrationstate_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0095_remove_rundata_flextable.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0096_remove_artifact__param_values_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0097_remove_schemaparam_param_remove_paramvalue_param_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0098_alter_feature_type_alter_project_type_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0099_alter_writelog_seqno.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0100_branch_alter_artifact__branch_code_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0101_alter_artifact_hash_alter_feature_name_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0102_remove_writelog_branch_code_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0103_remove_writelog_migration_state_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0104_alter_branch_uid.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0105_record_unique_name.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0106_transfer_data_migration.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0107_add_schema_to_record.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0108_remove_record_sheet_remove_sheetproject_sheet_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0109_record_input_of_runs_alter_record_run_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0110_rename_values_artifacts_record_linked_artifacts.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0111_remove_record__sort_order.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0112_alter_recordartifact_feature_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0113_lower_case_branch_and_space_names.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0114_alter_run__status_code.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0115_alter_space_uid.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0116_remove_artifact_unique_artifact_storage_key_hash_and_more.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/0117_fix_artifact_storage_hash_unique_constraints.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/migrations/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_describe.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_django.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_feature_manager.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_from_values.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_is_versioned.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_label_manager.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/_relations.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/artifact_set.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/can_curate.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/collection.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/feature.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/has_parents.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/query_manager.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/query_set.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/record.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/run.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/save.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/schema.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/sqlrecord.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/storage.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/transform.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/models/ulabel.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/py.typed +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/setup/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/setup/_switch.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/setup/core/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/setup/errors/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/lamindb/setup/types/__init__.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/noxfile.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/pyproject.toml +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/conftest.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/_dataset_fixtures.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/conftest.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/basic-r-notebook.Rmd.cleaned.html +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/basic-r-notebook.Rmd.html +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/duplicate/with-title-initialized-consecutive-finish.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/no-title.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/with-title-initialized-consecutive-finish-not-last-cell.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/notebooks/with-title-initialized-consecutive-finish.ipynb +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/duplicate1/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/duplicate2/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/duplicate3/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/duplicate4/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/duplicate5/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/script-to-test-filename-change.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/scripts/script-to-test-versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_artifact.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_artifact_folders.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_can_curate.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_collection.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_data.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_db.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_delete.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_describe_and_df_calls.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_dtype.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_feature.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_feature_label_manager.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_from_values.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_has_parents.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_integrity.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_load.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_manager.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_models.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_notebooks.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_queryset.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_record.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_run.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_save.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_schema.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_search.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_settings.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_storage.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_track.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_tracked.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_transform.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_ulabel.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_versioning.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_view.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/core/test_visibility.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/conftest.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_cat_managers.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_curate_from_croissant.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_curators_examples.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_curators_multivalue.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_cxg_curator.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_dataframe_curators_accounting_example.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/curators/test_records.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/conftest.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/jwt_utils.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/scripts/check_lamin_dev.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/scripts/clean_lamin_dev.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/scripts/setup_access.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/scripts/setup_instance.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/permissions/test_permissions.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_artifact_zarr.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_cache.py +0 -0
- {lamindb-1.10.1 → lamindb-1.10.2}/tests/storage/test_transfer.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: lamindb
|
3
|
-
Version: 1.10.
|
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,6 +9,7 @@ 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
15
|
Requires-Dist: lamindb_setup[aws]==1.9.1
|
@@ -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
|
-
|
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
|
@@ -13,12 +13,17 @@ from anndata import __version__ as anndata_version
|
|
13
13
|
from anndata._core.index import _normalize_indices
|
14
14
|
from anndata._core.views import _resolve_idx
|
15
15
|
from anndata._io.h5ad import read_dataframe_legacy as read_dataframe_legacy_h5
|
16
|
-
from anndata._io.specs.registry import
|
16
|
+
from anndata._io.specs.registry import (
|
17
|
+
get_spec,
|
18
|
+
read_elem,
|
19
|
+
read_elem_partial,
|
20
|
+
write_elem,
|
21
|
+
)
|
17
22
|
from anndata.compat import _read_attr
|
18
23
|
from fsspec.implementations.local import LocalFileSystem
|
19
24
|
from fsspec.utils import infer_compression
|
20
25
|
from lamin_utils import logger
|
21
|
-
from lamindb_setup.core.upath import infer_filesystem
|
26
|
+
from lamindb_setup.core.upath import S3FSMap, infer_filesystem
|
22
27
|
from packaging import version
|
23
28
|
from upath import UPath
|
24
29
|
|
@@ -28,6 +33,8 @@ if TYPE_CHECKING:
|
|
28
33
|
from fsspec.core import OpenFile
|
29
34
|
from lamindb_setup.types import UPathStr
|
30
35
|
|
36
|
+
from lamindb import Artifact
|
37
|
+
|
31
38
|
|
32
39
|
anndata_version_parse = version.parse(anndata_version)
|
33
40
|
|
@@ -300,6 +307,11 @@ if ZARR_INSTALLED:
|
|
300
307
|
|
301
308
|
store = get_zarr_store(filepath)
|
302
309
|
storage = zarr.open(store, mode=mode)
|
310
|
+
# zarr v2 re-initializes the mapper
|
311
|
+
# we need to put back the correct one
|
312
|
+
# S3FSMap is returned from get_zarr_store only for zarr v2
|
313
|
+
if isinstance(store, S3FSMap):
|
314
|
+
storage.store.map = store
|
303
315
|
conn = None
|
304
316
|
return conn, storage
|
305
317
|
|
@@ -438,9 +450,15 @@ def _try_backed_full(elem):
|
|
438
450
|
return read_elem(elem)
|
439
451
|
|
440
452
|
|
453
|
+
def _to_index(elem: np.ndarray):
|
454
|
+
if elem.dtype in (np.float64, np.int64):
|
455
|
+
elem = elem.astype(str)
|
456
|
+
return pd.Index(elem)
|
457
|
+
|
458
|
+
|
441
459
|
def _safer_read_index(elem):
|
442
460
|
if isinstance(elem, GroupTypes):
|
443
|
-
return
|
461
|
+
return _to_index(read_elem(elem[_read_attr(elem.attrs, "_index")]))
|
444
462
|
elif isinstance(elem, ArrayTypes):
|
445
463
|
indices = None
|
446
464
|
for index_name in ("index", "_index"):
|
@@ -450,7 +468,7 @@ def _safer_read_index(elem):
|
|
450
468
|
if indices is not None and len(indices) > 0:
|
451
469
|
if isinstance(indices[0], bytes):
|
452
470
|
indices = np.frompyfunc(lambda x: x.decode("utf-8"), 1, 1)(indices)
|
453
|
-
return
|
471
|
+
return _to_index(indices)
|
454
472
|
else:
|
455
473
|
raise ValueError("Indices not found.")
|
456
474
|
else:
|
@@ -479,33 +497,40 @@ class _MapAccessor:
|
|
479
497
|
return descr
|
480
498
|
|
481
499
|
|
500
|
+
def _safer_read_df(elem, indices=None):
|
501
|
+
if indices is not None:
|
502
|
+
obj = registry.safer_read_partial(elem, indices=indices)
|
503
|
+
df = _records_to_df(obj)
|
504
|
+
else:
|
505
|
+
df = registry.read_dataframe(elem)
|
506
|
+
if df.index.dtype in (np.float64, np.int64):
|
507
|
+
df.index = df.index.astype(str)
|
508
|
+
return df
|
509
|
+
|
510
|
+
|
482
511
|
class _AnnDataAttrsMixin:
|
483
512
|
storage: StorageType
|
484
513
|
_attrs_keys: Mapping[str, list]
|
485
514
|
|
486
515
|
@cached_property
|
487
|
-
def obs(self) -> pd.DataFrame:
|
516
|
+
def obs(self) -> pd.DataFrame | None:
|
488
517
|
if "obs" not in self._attrs_keys:
|
489
518
|
return None
|
490
519
|
indices = getattr(self, "indices", None)
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
else:
|
496
|
-
return registry.read_dataframe(self.storage["obs"]) # type: ignore
|
520
|
+
return _safer_read_df(
|
521
|
+
self.storage["obs"], # type: ignore
|
522
|
+
indices=(indices[0], slice(None)) if indices is not None else None,
|
523
|
+
)
|
497
524
|
|
498
525
|
@cached_property
|
499
|
-
def var(self) -> pd.DataFrame:
|
526
|
+
def var(self) -> pd.DataFrame | None:
|
500
527
|
if "var" not in self._attrs_keys:
|
501
528
|
return None
|
502
529
|
indices = getattr(self, "indices", None)
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
else:
|
508
|
-
return registry.read_dataframe(self.storage["var"]) # type: ignore
|
530
|
+
return _safer_read_df(
|
531
|
+
self.storage["var"], # type: ignore
|
532
|
+
indices=(indices[1], slice(None)) if indices is not None else None,
|
533
|
+
)
|
509
534
|
|
510
535
|
@cached_property
|
511
536
|
def uns(self):
|
@@ -702,6 +727,7 @@ class AnnDataAccessor(_AnnDataAttrsMixin):
|
|
702
727
|
connection: OpenFile | None,
|
703
728
|
storage: StorageType,
|
704
729
|
filename: str,
|
730
|
+
artifact: Artifact | None = None,
|
705
731
|
):
|
706
732
|
self._conn = connection
|
707
733
|
self.storage = storage
|
@@ -713,6 +739,11 @@ class AnnDataAccessor(_AnnDataAttrsMixin):
|
|
713
739
|
self._obs_names = _safer_read_index(self.storage["obs"]) # type: ignore
|
714
740
|
self._var_names = _safer_read_index(self.storage["var"]) # type: ignore
|
715
741
|
|
742
|
+
self._artifact = artifact # save artifact to update in write mode
|
743
|
+
|
744
|
+
self._updated = False # track updates in r+ mode for zarr
|
745
|
+
|
746
|
+
self._entered = False # check that the context manager is used
|
716
747
|
self._closed = False
|
717
748
|
|
718
749
|
def close(self):
|
@@ -723,11 +754,23 @@ class AnnDataAccessor(_AnnDataAttrsMixin):
|
|
723
754
|
self._conn.close()
|
724
755
|
self._closed = True
|
725
756
|
|
757
|
+
if self._updated and (artifact := self._artifact) is not None:
|
758
|
+
from lamindb.models.artifact import Artifact
|
759
|
+
from lamindb.models.sqlrecord import init_self_from_db
|
760
|
+
|
761
|
+
new_version = Artifact(
|
762
|
+
artifact.path, revises=artifact, _is_internal_call=True
|
763
|
+
).save()
|
764
|
+
# note: sets _state.db = "default"
|
765
|
+
init_self_from_db(artifact, new_version)
|
766
|
+
|
726
767
|
@property
|
727
768
|
def closed(self):
|
728
769
|
return self._closed
|
729
770
|
|
730
771
|
def __enter__(self):
|
772
|
+
self._entered = True
|
773
|
+
|
731
774
|
return self
|
732
775
|
|
733
776
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
@@ -763,6 +806,35 @@ class AnnDataAccessor(_AnnDataAttrsMixin):
|
|
763
806
|
self.storage["raw"], None, None, self._obs_names, None, self.shape[0]
|
764
807
|
)
|
765
808
|
|
809
|
+
def add_column(
|
810
|
+
self,
|
811
|
+
where: Literal["obs", "var"],
|
812
|
+
col_name: str,
|
813
|
+
col: np.ndarray | pd.Categorical,
|
814
|
+
):
|
815
|
+
"""Add a new column to .obs or .var of the underlying AnnData object."""
|
816
|
+
df_store = self.storage[where] # type: ignore
|
817
|
+
if getattr(df_store, "read_only", True):
|
818
|
+
raise ValueError(
|
819
|
+
"You can use .add_column(...) only with zarr in a writable mode."
|
820
|
+
)
|
821
|
+
write_elem(df_store, col_name, col)
|
822
|
+
df_store.attrs["column-order"] = df_store.attrs["column-order"] + [col_name]
|
823
|
+
# remind only once if this wasn't updated before and not in the context manager
|
824
|
+
if not self._updated and not self._entered and self._artifact is not None:
|
825
|
+
logger.important(
|
826
|
+
"Do not forget to call .close() after you finish "
|
827
|
+
f"working with this accessor for {self._name} "
|
828
|
+
"to automatically update the corresponding artifact."
|
829
|
+
)
|
830
|
+
|
831
|
+
self._updated = True
|
832
|
+
# reset the cached property
|
833
|
+
# todo: maybe just append the column if the df was already loaded
|
834
|
+
self.__dict__.pop(where, None)
|
835
|
+
# update the cached columns
|
836
|
+
self._attrs_keys[where].append(col_name)
|
837
|
+
|
766
838
|
|
767
839
|
# get the number of observations in an anndata object or file fast and safely
|
768
840
|
def _anndata_n_observations(object: UPathStr | AnnData) -> int | None:
|
@@ -4,6 +4,7 @@ from dataclasses import dataclass
|
|
4
4
|
from pathlib import Path
|
5
5
|
from typing import TYPE_CHECKING, Any, Callable, Literal
|
6
6
|
|
7
|
+
import h5py
|
7
8
|
from anndata._io.specs.registry import get_spec
|
8
9
|
|
9
10
|
from ._anndata_accessor import AnnDataAccessor, StorageType, registry
|
@@ -92,10 +93,10 @@ def backed_access(
|
|
92
93
|
from lamindb.models import Artifact
|
93
94
|
|
94
95
|
if isinstance(artifact_or_filepath, Artifact):
|
95
|
-
|
96
|
-
|
97
|
-
)
|
96
|
+
artifact = artifact_or_filepath
|
97
|
+
objectpath, _ = filepath_from_artifact(artifact, using_key=using_key)
|
98
98
|
else:
|
99
|
+
artifact = None
|
99
100
|
objectpath = artifact_or_filepath
|
100
101
|
name = objectpath.name
|
101
102
|
# ignore .gz, only check the real suffix
|
@@ -111,9 +112,11 @@ def backed_access(
|
|
111
112
|
elif suffix in {".h5", ".hdf5", ".h5ad"}:
|
112
113
|
conn, storage = registry.open("h5py", objectpath, mode=mode, **kwargs)
|
113
114
|
elif suffix == ".zarr":
|
115
|
+
if mode not in {"r", "r+"}:
|
116
|
+
raise ValueError("`mode` should be either 'r' or 'r+' for zarr.")
|
114
117
|
conn, storage = registry.open("zarr", objectpath, mode=mode, **kwargs)
|
115
118
|
if "spatialdata_attrs" in storage.attrs:
|
116
|
-
return SpatialDataAccessor(storage, name)
|
119
|
+
return SpatialDataAccessor(storage, name, artifact)
|
117
120
|
elif len(df_suffixes := _flat_suffixes(objectpath)) == 1 and (
|
118
121
|
df_suffix := df_suffixes.pop()
|
119
122
|
) in set(PYARROW_SUFFIXES).union(POLARS_SUFFIXES):
|
@@ -127,9 +130,9 @@ def backed_access(
|
|
127
130
|
|
128
131
|
is_anndata = suffix == ".h5ad" or get_spec(storage).encoding_type == "anndata"
|
129
132
|
if is_anndata:
|
130
|
-
if mode != "r":
|
131
|
-
raise ValueError("Can only access `AnnData` with mode='r'.")
|
132
|
-
return AnnDataAccessor(conn, storage, name)
|
133
|
+
if mode != "r" and isinstance(storage, h5py.Group):
|
134
|
+
raise ValueError("Can only access `hdf5` `AnnData` with mode='r'.")
|
135
|
+
return AnnDataAccessor(conn, storage, name, artifact)
|
133
136
|
else:
|
134
137
|
return BackedAccessor(conn, storage)
|
135
138
|
|
@@ -8,13 +8,22 @@ from ._anndata_accessor import AnnDataAccessor
|
|
8
8
|
if TYPE_CHECKING:
|
9
9
|
from zarr import Group
|
10
10
|
|
11
|
+
from lamindb import Artifact
|
12
|
+
|
11
13
|
|
12
14
|
class _TablesAccessor:
|
13
|
-
def __init__(self, tables: Group):
|
15
|
+
def __init__(self, tables: Group, artifact: Artifact | None = None):
|
14
16
|
self._tables = tables
|
15
17
|
|
18
|
+
self._artifact = artifact
|
19
|
+
|
16
20
|
def __getitem__(self, key: str) -> AnnDataAccessor:
|
17
|
-
return AnnDataAccessor(
|
21
|
+
return AnnDataAccessor(
|
22
|
+
connection=None,
|
23
|
+
storage=self._tables[key],
|
24
|
+
filename=key,
|
25
|
+
artifact=self._artifact,
|
26
|
+
)
|
18
27
|
|
19
28
|
def keys(self) -> list[str]:
|
20
29
|
return list(self._tables.keys())
|
@@ -33,14 +42,16 @@ class SpatialDataAccessor:
|
|
33
42
|
For now only allows to access `tables`.
|
34
43
|
"""
|
35
44
|
|
36
|
-
def __init__(self, storage: Group, name: str):
|
45
|
+
def __init__(self, storage: Group, name: str, artifact: Artifact | None = None):
|
37
46
|
self.storage = storage
|
38
47
|
self._name = name
|
39
48
|
|
49
|
+
self._artifact = artifact
|
50
|
+
|
40
51
|
@cached_property
|
41
52
|
def tables(self) -> _TablesAccessor:
|
42
53
|
"""tables of the underlying SpatialData object."""
|
43
|
-
return _TablesAccessor(self.storage["tables"])
|
54
|
+
return _TablesAccessor(self.storage["tables"], self._artifact)
|
44
55
|
|
45
56
|
def __repr__(self):
|
46
57
|
"""Description of the SpatialDataAccessor object."""
|
@@ -37,6 +37,9 @@ def get_zarr_store(
|
|
37
37
|
if isinstance(storepath, LocalPathClasses):
|
38
38
|
store = storepath_str
|
39
39
|
elif IS_ZARR_V3:
|
40
|
+
# todo: also check how to treat non-asynchronous filesystems
|
41
|
+
# zarr has something for this, using fsspec async wrapper
|
42
|
+
# check FsspecStore code
|
40
43
|
store = zarr.storage.FsspecStore.from_upath(UPath(storepath, asynchronous=True))
|
41
44
|
else:
|
42
45
|
store = create_mapper(storepath.fs, storepath_str, check=check, create=create)
|
@@ -364,12 +364,13 @@ class SlotsCurator(Curator):
|
|
364
364
|
)
|
365
365
|
break
|
366
366
|
|
367
|
-
self._artifact.schema = self._schema
|
368
|
-
self._artifact.save()
|
369
367
|
cat_vectors = {}
|
370
368
|
for curator in self._slots.values():
|
371
369
|
for key, cat_vector in curator.cat._cat_vectors.items():
|
372
370
|
cat_vectors[key] = cat_vector
|
371
|
+
|
372
|
+
self._artifact.schema = self._schema
|
373
|
+
self._artifact.save()
|
373
374
|
return annotate_artifact( # type: ignore
|
374
375
|
self._artifact,
|
375
376
|
curator=self,
|
@@ -685,10 +686,11 @@ class DataFrameCurator(Curator):
|
|
685
686
|
description=description,
|
686
687
|
revises=revises,
|
687
688
|
run=run,
|
688
|
-
format=".csv" if key.endswith(".csv") else None,
|
689
|
+
format=".csv" if key is not None and key.endswith(".csv") else None,
|
689
690
|
)
|
690
|
-
|
691
|
-
|
691
|
+
|
692
|
+
self._artifact.schema = self._schema
|
693
|
+
self._artifact.save()
|
692
694
|
return annotate_artifact( # type: ignore
|
693
695
|
self._artifact,
|
694
696
|
cat_vectors=self.cat._cat_vectors,
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Generated by Django 5.2 on 2025-08-07 15:28
|
2
|
+
|
3
|
+
import django.db.models.deletion
|
4
|
+
import django.db.models.functions.datetime
|
5
|
+
from django.db import migrations, models
|
6
|
+
|
7
|
+
import lamindb.base.fields
|
8
|
+
import lamindb.base.users
|
9
|
+
import lamindb.models.run
|
10
|
+
import lamindb.models.sqlrecord
|
11
|
+
|
12
|
+
|
13
|
+
class Migration(migrations.Migration):
|
14
|
+
dependencies = [
|
15
|
+
("lamindb", "0117_fix_artifact_storage_hash_unique_constraints"),
|
16
|
+
]
|
17
|
+
|
18
|
+
operations = [
|
19
|
+
migrations.AlterField(
|
20
|
+
model_name="recordproject",
|
21
|
+
name="value",
|
22
|
+
field=lamindb.base.fields.ForeignKey(
|
23
|
+
blank=True,
|
24
|
+
on_delete=django.db.models.deletion.PROTECT,
|
25
|
+
related_name="links_in_record",
|
26
|
+
to="lamindb.project",
|
27
|
+
),
|
28
|
+
),
|
29
|
+
migrations.CreateModel(
|
30
|
+
name="ProjectRecord",
|
31
|
+
fields=[
|
32
|
+
(
|
33
|
+
"created_at",
|
34
|
+
lamindb.base.fields.DateTimeField(
|
35
|
+
blank=True,
|
36
|
+
db_default=django.db.models.functions.datetime.Now(),
|
37
|
+
db_index=True,
|
38
|
+
editable=False,
|
39
|
+
),
|
40
|
+
),
|
41
|
+
("id", models.BigAutoField(primary_key=True, serialize=False)),
|
42
|
+
(
|
43
|
+
"created_by",
|
44
|
+
lamindb.base.fields.ForeignKey(
|
45
|
+
blank=True,
|
46
|
+
default=lamindb.base.users.current_user_id,
|
47
|
+
editable=False,
|
48
|
+
on_delete=django.db.models.deletion.PROTECT,
|
49
|
+
related_name="+",
|
50
|
+
to="lamindb.user",
|
51
|
+
),
|
52
|
+
),
|
53
|
+
(
|
54
|
+
"feature",
|
55
|
+
lamindb.base.fields.ForeignKey(
|
56
|
+
blank=True,
|
57
|
+
default=None,
|
58
|
+
null=True,
|
59
|
+
on_delete=django.db.models.deletion.PROTECT,
|
60
|
+
related_name="links_projectrecord",
|
61
|
+
to="lamindb.feature",
|
62
|
+
),
|
63
|
+
),
|
64
|
+
(
|
65
|
+
"project",
|
66
|
+
lamindb.base.fields.ForeignKey(
|
67
|
+
blank=True,
|
68
|
+
on_delete=django.db.models.deletion.PROTECT,
|
69
|
+
related_name="links_record",
|
70
|
+
to="lamindb.project",
|
71
|
+
),
|
72
|
+
),
|
73
|
+
(
|
74
|
+
"record",
|
75
|
+
lamindb.base.fields.ForeignKey(
|
76
|
+
blank=True,
|
77
|
+
on_delete=django.db.models.deletion.CASCADE,
|
78
|
+
related_name="links_project",
|
79
|
+
to="lamindb.record",
|
80
|
+
),
|
81
|
+
),
|
82
|
+
(
|
83
|
+
"run",
|
84
|
+
lamindb.base.fields.ForeignKey(
|
85
|
+
blank=True,
|
86
|
+
default=lamindb.models.run.current_run,
|
87
|
+
null=True,
|
88
|
+
on_delete=django.db.models.deletion.PROTECT,
|
89
|
+
related_name="+",
|
90
|
+
to="lamindb.run",
|
91
|
+
),
|
92
|
+
),
|
93
|
+
],
|
94
|
+
options={
|
95
|
+
"unique_together": {("record", "project", "feature")},
|
96
|
+
},
|
97
|
+
bases=(lamindb.models.sqlrecord.IsLink, models.Model),
|
98
|
+
),
|
99
|
+
]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Generated by Django 5.2 on 2025-08-09 13:31
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
dependencies = [
|
8
|
+
("lamindb", "0118_alter_recordproject_value_projectrecord"),
|
9
|
+
]
|
10
|
+
|
11
|
+
operations = [
|
12
|
+
migrations.RenameField(
|
13
|
+
model_name="project",
|
14
|
+
old_name="records",
|
15
|
+
new_name="linked_in_records",
|
16
|
+
),
|
17
|
+
migrations.AddField(
|
18
|
+
model_name="project",
|
19
|
+
name="records",
|
20
|
+
field=models.ManyToManyField(
|
21
|
+
related_name="projects",
|
22
|
+
through="lamindb.ProjectRecord",
|
23
|
+
to="lamindb.record",
|
24
|
+
),
|
25
|
+
),
|
26
|
+
]
|