Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encapsulate methods for working with Dandiset versions at the WebDAV level #159

Merged
merged 2 commits into from
Jul 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 83 additions & 61 deletions src/dav/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use crate::consts::{DAV_XML_CONTENT_TYPE, HTML_CONTENT_TYPE};
use crate::dandi::*;
use crate::paths::Component;
use crate::paths::PurePath;
use crate::zarrman::*;
use axum::{
body::Body,
Expand Down Expand Up @@ -145,47 +146,29 @@
.into_response())
}

async fn get_version_endpoint(
&self,
dandiset_id: &DandisetId,
version: &VersionSpec,
) -> Result<VersionEndpoint<'_>, DavError> {
async fn get_version_handler<'a>(
&'a self,
dandiset_id: &'a DandisetId,
version_spec: &'a VersionSpec,
) -> Result<VersionHandler<'a>, DavError> {

Check warning on line 153 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L149-L153

Added lines #L149 - L153 were not covered by tests
let d = self.dandi.dandiset(dandiset_id.clone());
match version {
VersionSpec::Draft => Ok(d.version(VersionId::Draft)),
VersionSpec::Published(v) => Ok(d.version(VersionId::Published(v.clone()))),
let endpoint = match version_spec {
VersionSpec::Draft => d.version(VersionId::Draft),
VersionSpec::Published(v) => d.version(VersionId::Published(v.clone())),

Check warning on line 157 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L155-L157

Added lines #L155 - L157 were not covered by tests
VersionSpec::Latest => match d.get().await?.most_recent_published_version {
Some(DandisetVersion { version, .. }) => Ok(d.version(version)),
None => Err(DavError::NoLatestVersion {
dandiset_id: dandiset_id.clone(),
}),
Some(DandisetVersion { version, .. }) => d.version(version),

Check warning on line 159 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L159

Added line #L159 was not covered by tests
None => {
return Err(DavError::NoLatestVersion {
dandiset_id: dandiset_id.clone(),
})

Check warning on line 163 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L161-L163

Added lines #L161 - L163 were not covered by tests
}
},
}
}

async fn get_dandiset_yaml(
&self,
dandiset_id: &DandisetId,
version: &VersionSpec,
) -> Result<DavItem, DavError> {
let md = self
.get_version_endpoint(dandiset_id, version)
.await?
.get_metadata()
.await?;
Ok(DavItem::from(md).under_version_path(dandiset_id, version))
}

async fn get_dandiset_version(
&self,
dandiset_id: &DandisetId,
version: &VersionSpec,
) -> Result<(DavCollection, VersionEndpoint<'_>), DavError> {
let endpoint = self.get_version_endpoint(dandiset_id, version).await?;
let v = endpoint.get().await?;
let path = version_path(dandiset_id, version);
let col = DavCollection::dandiset_version(v, path);
Ok((col, endpoint))
};
Ok(VersionHandler {
dandiset_id,
version_spec,
endpoint,
})

Check warning on line 171 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L167-L171

Added lines #L167 - L171 were not covered by tests
}

async fn resolve(&self, path: &DavPath) -> Result<DavResource, DavError> {
Expand All @@ -207,27 +190,29 @@
dandiset_id,
version,
} => self
.get_dandiset_version(dandiset_id, version)
.get_version_handler(dandiset_id, version)
.await?
.get()

Check warning on line 195 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L193-L195

Added lines #L193 - L195 were not covered by tests
.await
.map(|(col, _)| DavResource::Collection(col)),
.map(DavResource::Collection),

Check warning on line 197 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L197

Added line #L197 was not covered by tests
DavPath::DandisetYaml {
dandiset_id,
version,
} => self
.get_dandiset_yaml(dandiset_id, version)
.get_version_handler(dandiset_id, version)
.await?
.get_dandiset_yaml()

Check warning on line 204 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L202-L204

Added lines #L202 - L204 were not covered by tests
.await
.map(DavResource::Item),
DavPath::DandiResource {
dandiset_id,
version,
path,
} => {
let res = self
.get_version_endpoint(dandiset_id, version)
self.get_version_handler(dandiset_id, version)

Check warning on line 212 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L212

Added line #L212 was not covered by tests
.await?
.get_resource(path)
.await?;
Ok(DavResource::from(res).under_version_path(dandiset_id, version))
.await

Check warning on line 215 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L215

Added line #L215 was not covered by tests
}
DavPath::ZarrIndex => Ok(DavResource::Collection(DavCollection::zarr_index())),
DavPath::ZarrPath { path } => {
Expand Down Expand Up @@ -296,37 +281,30 @@
dandiset_id,
version,
} => {
let (col, endpoint) = self.get_dandiset_version(dandiset_id, version).await?;
let mut children = endpoint
.get_root_children()
.map_ok(|res| DavResource::from(res).under_version_path(dandiset_id, version))
.try_collect::<Vec<_>>()
.await?;
children.push(
self.get_dandiset_yaml(dandiset_id, version)
.await
.map(DavResource::Item)?,
);
let handler = self.get_version_handler(dandiset_id, version).await?;
let col = handler.get().await?;
let mut children = handler.get_root_children().await?;
children.push(handler.get_dandiset_yaml().await.map(DavResource::Item)?);

Check warning on line 287 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L284-L287

Added lines #L284 - L287 were not covered by tests
Ok(DavResourceWithChildren::Collection { col, children })
}
DavPath::DandisetYaml {
dandiset_id,
version,
} => self
.get_dandiset_yaml(dandiset_id, version)
.get_version_handler(dandiset_id, version)
.await?
.get_dandiset_yaml()

Check warning on line 296 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L294-L296

Added lines #L294 - L296 were not covered by tests
.await
.map(DavResourceWithChildren::Item),
DavPath::DandiResource {
dandiset_id,
version,
path,
} => {
let res = self
.get_version_endpoint(dandiset_id, version)
self.get_version_handler(dandiset_id, version)

Check warning on line 304 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L304

Added line #L304 was not covered by tests
.await?
.get_resource_with_children(path)
.await?;
Ok(DavResourceWithChildren::from(res).under_version_path(dandiset_id, version))
.await

Check warning on line 307 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L307

Added line #L307 was not covered by tests
}
DavPath::ZarrIndex => {
let col = DavCollection::zarr_index();
Expand All @@ -347,6 +325,50 @@
}
}

#[derive(Clone, Debug)]
struct VersionHandler<'a> {
dandiset_id: &'a DandisetId,
version_spec: &'a VersionSpec,
endpoint: VersionEndpoint<'a>,
}

impl VersionHandler<'_> {
async fn get(&self) -> Result<DavCollection, DavError> {
let v = self.endpoint.get().await?;
let path = version_path(self.dandiset_id, self.version_spec);
Ok(DavCollection::dandiset_version(v, path))
}

Check warning on line 340 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L336-L340

Added lines #L336 - L340 were not covered by tests

async fn get_root_children(&self) -> Result<Vec<DavResource>, DandiError> {
self.endpoint
.get_root_children()
.map_ok(|res| {
DavResource::from(res).under_version_path(self.dandiset_id, self.version_spec)
})
.try_collect::<Vec<_>>()
.await
}

Check warning on line 350 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L342-L350

Added lines #L342 - L350 were not covered by tests

async fn get_dandiset_yaml(&self) -> Result<DavItem, DavError> {
let md = self.endpoint.get_metadata().await?;
Ok(DavItem::from(md).under_version_path(self.dandiset_id, self.version_spec))
}

Check warning on line 355 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L352-L355

Added lines #L352 - L355 were not covered by tests

async fn get_resource(&self, path: &PurePath) -> Result<DavResource, DavError> {
let res = self.endpoint.get_resource(path).await?;
Ok(DavResource::from(res).under_version_path(self.dandiset_id, self.version_spec))
}

Check warning on line 360 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L357-L360

Added lines #L357 - L360 were not covered by tests

async fn get_resource_with_children(
&self,
path: &PurePath,
) -> Result<DavResourceWithChildren, DavError> {
let res = self.endpoint.get_resource_with_children(path).await?;
Ok(DavResourceWithChildren::from(res)
.under_version_path(self.dandiset_id, self.version_spec))
}

Check warning on line 369 in src/dav/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dav/mod.rs#L362-L369

Added lines #L362 - L369 were not covered by tests
}

#[derive(Debug, Error)]
pub(crate) enum DavError {
#[error("failed to fetch data from Archive")]
Expand Down