diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 5b00f743c..95960825e 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -554,19 +554,83 @@ def get_dandiset( return d.for_version(version_id) return d - def get_dandisets(self) -> Iterator[RemoteDandiset]: + def get_dandisets( + self, + *, + draft: bool | None = None, + embargoed: bool | None = None, + empty: bool | None = None, + mine: bool | None = None, + order: str | None = None, + search: str | None = None, + ) -> Iterator[RemoteDandiset]: """ Returns a generator of all Dandisets on the server. For each Dandiset, the `RemoteDandiset`'s version is set to the most recent published version if there is one, otherwise to the draft version. - """ - for data in self.paginate("/dandisets/"): + + .. versionchanged:: 0.61.0 + + ``draft``, ``embargoed``, ``empty``, ``mine``, ``order``, and + ``search`` parameters added + + :param draft: + If true, Dandisets that have only draft versions (i.e., that + haven't yet been published) will be included in the results + (default true) + + :param embargoed: + If true, embargoed Dandisets will be included in the results + (default false) + + :param empty: + If true, empty Dandisets will be included in the results (default + true) + + :param mine: + If true, only Dandisets owned by the authenticated user will be + retrieved (default false) + + :param order: + The field to sort the results by. The accepted field names are + ``"id"``, ``"name"``, ``"modified"``, and ``"size"``. Prepend a + hyphen to the field name to reverse the sort order. + + :param search: + A search string to filter the returned Dandisets by. The string is + searched for in the metadata of Dandiset versions. + """ + for data in self.paginate( + "/dandisets/", + params={ + "draft": draft, + "embargoed": embargoed, + "empty": empty, + "ordering": order, + "search": search, + "user": "me" if mine else None, + }, + ): yield RemoteDandiset.from_data(self, data) - def create_dandiset(self, name: str, metadata: dict[str, Any]) -> RemoteDandiset: - """Creates a Dandiset with the given name & metadata""" + def create_dandiset( + self, name: str, metadata: dict[str, Any], *, embargo: bool = False + ) -> RemoteDandiset: + """ + Creates a Dandiset with the given name & metadata. If ``embargo`` is + `True`, the resulting Dandiset will be embargoed. + + .. versionchanged:: 0.61.0 + + ``embargo`` argument added + """ return RemoteDandiset.from_data( - self, self.post("/dandisets/", json={"name": name, "metadata": metadata}) + self, + self.post( + "/dandisets/", + json={"name": name, "metadata": metadata}, + params={"embargo": "true" if embargo else "false"}, + ), ) def check_schema_version(self, schema_version: str | None = None) -> None: diff --git a/dandi/tests/fixtures.py b/dandi/tests/fixtures.py index 2981ddd62..a18123e15 100644 --- a/dandi/tests/fixtures.py +++ b/dandi/tests/fixtures.py @@ -520,7 +520,7 @@ class SampleDandisetFactory: local_dandi_api: DandiAPI tmp_path_factory: pytest.TempPathFactory - def mkdandiset(self, name: str) -> SampleDandiset: + def mkdandiset(self, name: str, embargo: bool = False) -> SampleDandiset: d = self.local_dandi_api.client.create_dandiset( name, # Minimal metadata needed to create a publishable Dandiset: @@ -539,6 +539,7 @@ def mkdandiset(self, name: str) -> SampleDandiset: } ], }, + embargo=embargo, ) dspath = self.tmp_path_factory.mktemp("dandiset") (dspath / dandiset_metadata_file).write_text(f"identifier: '{d.identifier}'\n") diff --git a/dandi/tests/test_dandiapi.py b/dandi/tests/test_dandiapi.py index 077f16ce7..38d558da7 100644 --- a/dandi/tests/test_dandiapi.py +++ b/dandi/tests/test_dandiapi.py @@ -16,7 +16,7 @@ import requests import responses -from .fixtures import DandiAPI, SampleDandiset +from .fixtures import DandiAPI, SampleDandiset, SampleDandisetFactory from .skip import mark from .. import dandiapi from ..consts import ( @@ -329,7 +329,47 @@ def test_check_schema_version_mismatch() -> None: def test_get_dandisets(text_dandiset: SampleDandiset) -> None: dandisets = list(text_dandiset.client.get_dandisets()) - assert sum(1 for d in dandisets if d.identifier == text_dandiset.dandiset_id) == 1 + assert text_dandiset.dandiset_id in [d.identifier for d in dandisets] + + +def test_get_embargoed_dandisets( + sample_dandiset_factory: SampleDandisetFactory, +) -> None: + ds = sample_dandiset_factory.mkdandiset("Embargoed Dandiset", embargo=True) + dandisets = list(ds.client.get_dandisets(embargoed=True)) + assert ds.dandiset_id in [d.identifier for d in dandisets] + dandisets = list(ds.client.get_dandisets(embargoed=False)) + assert ds.dandiset_id not in [d.identifier for d in dandisets] + dandisets = list(ds.client.get_dandisets(embargoed=None)) + assert ds.dandiset_id not in [d.identifier for d in dandisets] + + +def test_get_draft_dandisets(new_dandiset: SampleDandiset) -> None: + dandisets = list(new_dandiset.client.get_dandisets(draft=True)) + assert new_dandiset.dandiset_id in [d.identifier for d in dandisets] + dandisets = list(new_dandiset.client.get_dandisets(draft=False)) + assert new_dandiset.dandiset_id not in [d.identifier for d in dandisets] + dandisets = list(new_dandiset.client.get_dandisets(draft=None)) + assert new_dandiset.dandiset_id in [d.identifier for d in dandisets] + + +def test_get_empty_dandisets(new_dandiset: SampleDandiset) -> None: + dandisets = list(new_dandiset.client.get_dandisets(empty=True)) + assert new_dandiset.dandiset_id in [d.identifier for d in dandisets] + dandisets = list(new_dandiset.client.get_dandisets(empty=False)) + assert new_dandiset.dandiset_id not in [d.identifier for d in dandisets] + dandisets = list(new_dandiset.client.get_dandisets(empty=None)) + assert new_dandiset.dandiset_id in [d.identifier for d in dandisets] + + +def test_search_get_dandisets( + sample_dandiset_factory: SampleDandisetFactory, +) -> None: + ds = sample_dandiset_factory.mkdandiset("Unicorn Dandiset") + dandisets = list(ds.client.get_dandisets(search="Unicorn")) + assert ds.dandiset_id in [d.identifier for d in dandisets] + dandisets = list(ds.client.get_dandisets(search="Dragon")) + assert ds.dandiset_id not in [d.identifier for d in dandisets] def test_get_dandiset_lazy(