Skip to content
Draft
Show file tree
Hide file tree
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
29 changes: 15 additions & 14 deletions api/scpca_portal/models/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.db.models import Count
from django.db.models.query import QuerySet
from django.utils.timezone import make_aware

from typing_extensions import Self
Expand Down Expand Up @@ -627,14 +628,14 @@ def get_includes_files_multiplexed(self) -> bool:

# ASSOCIATIONS WITH OTHER MODELS
@property
def projects(self) -> Iterable[Project]:
def projects(self) -> QuerySet[Project]:
"""Returns all project instances associated with the dataset."""
if project_ids := self.data.keys():
return Project.objects.filter(scpca_id__in=project_ids).order_by("scpca_id")
return Project.objects.none()

@property
def spatial_projects(self) -> Iterable[Project]:
def spatial_projects(self) -> QuerySet[Project]:
"""
Returns all project instances which have spatial data
with spatial samples requested in the data attribute.
Expand All @@ -652,7 +653,7 @@ def spatial_projects(self) -> Iterable[Project]:
return Project.objects.none()

@property
def single_cell_projects(self) -> Iterable[Project]:
def single_cell_projects(self) -> QuerySet[Project]:
"""
Returns all project instances which have single cell data
with single cell samples requested in the data attribute.
Expand All @@ -667,7 +668,7 @@ def single_cell_projects(self) -> Iterable[Project]:
return Project.objects.none()

@property
def bulk_single_cell_projects(self) -> Iterable[Project]:
def bulk_single_cell_projects(self) -> QuerySet[Project]:
"""
Returns all project instances which have bulk data
where bulk was requested in the data attribute.
Expand All @@ -682,7 +683,7 @@ def bulk_single_cell_projects(self) -> Iterable[Project]:
return Project.objects.none()

@property
def cite_seq_projects(self) -> Iterable[Project]:
def cite_seq_projects(self) -> QuerySet[Project]:
"""
Returns all project instances associated with the dataset
which have cite seq data.
Expand All @@ -694,7 +695,7 @@ def cite_seq_projects(self) -> Iterable[Project]:
return self.projects.filter(has_cite_seq_data=True)

@property
def merged_projects(self) -> Iterable[Project]:
def merged_projects(self) -> QuerySet[Project]:
"""
Returns all project instances which have merged data
where merged was requested in the data attribute single cell field.
Expand All @@ -715,7 +716,7 @@ def merged_projects(self) -> Iterable[Project]:
return Project.objects.none()

@property
def multiplexed_projects(self) -> Iterable[Project]:
def multiplexed_projects(self) -> QuerySet[Project]:
"""
Returns all project instances which have multiplexed data.
"""
Expand All @@ -738,7 +739,7 @@ def has_lockfile_projects(self) -> bool:
return self.contains_project_ids(set(lockfile.get_locked_project_ids()))

@property
def locked_projects(self) -> Iterable[Project]:
def locked_projects(self) -> QuerySet[Project]:
"""Returns a queryset of all of the dataset's locked project."""
return self.projects.filter(is_locked=True)

Expand All @@ -756,7 +757,7 @@ def is_locked(self) -> bool:
return self.has_locked_projects or self.has_lockfile_projects

@property
def samples(self) -> Iterable[Sample]:
def samples(self) -> QuerySet[Sample]:
"""
Returns a queryset of all samples contained in data attribute.
If a sample is present in more than one modality, it will be
Expand All @@ -766,7 +767,7 @@ def samples(self) -> Iterable[Sample]:
[Modalities.SINGLE_CELL, Modalities.SPATIAL, Modalities.BULK_RNA_SEQ]
)

def get_selected_samples(self, modalities: Iterable[Modalities] = []) -> Iterable[Sample]:
def get_selected_samples(self, modalities: Iterable[Modalities] = []) -> QuerySet[Sample]:
"""
Returns a queryset of samples for the specified modalities
contained in data attribute.
Expand All @@ -780,7 +781,7 @@ def get_selected_samples(self, modalities: Iterable[Modalities] = []) -> Iterabl

def get_project_modality_samples(
self, project_id: str, modality: Modalities
) -> Iterable[Library]:
) -> QuerySet[Library]:
"""
Takes project's scpca_id and a modality.
Returns Sample instances defined in data attribute.
Expand All @@ -800,7 +801,7 @@ def get_project_modality_samples(
return project_samples.filter(scpca_id__in=project_data.get(modality, []))

@property
def libraries(self) -> Iterable[Library]:
def libraries(self) -> QuerySet[Library]:
"""Returns all of a Dataset's library, based on Data and Format attrs."""
dataset_libraries = Library.objects.none()

Expand All @@ -812,7 +813,7 @@ def libraries(self) -> Iterable[Library]:

def get_project_modality_libraries(
self, project_id: str, modality: Modalities
) -> Iterable[Library]:
) -> QuerySet[Library]:
"""
Takes project's scpca_id and a modality.
Returns Library instances associated with Samples defined in data attribute.
Expand All @@ -832,7 +833,7 @@ def get_is_merged_project(self, project_id) -> bool:
return self.data.get(project_id, {}).get(Modalities.SINGLE_CELL.value) == "MERGED"

@property
def original_files(self) -> Iterable[OriginalFile]:
def original_files(self) -> QuerySet[OriginalFile]:
"""Returns all of a Dataset's associated OriginalFiles."""
files = OriginalFile.objects.none()

Expand Down
7 changes: 4 additions & 3 deletions api/scpca_portal/models/original_file.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from collections import defaultdict
from pathlib import Path
from typing import Dict, Iterable, List, Tuple
from typing import Dict, List, Tuple

from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.db.models.query import QuerySet

from typing_extensions import Self

Expand Down Expand Up @@ -164,7 +165,7 @@ def bulk_update_from_dicts(
@staticmethod
def purge_deleted_files(
bucket: str, sync_timestamp, allow_bucket_wipe: bool = False
) -> List[Self]:
) -> QuerySet["OriginalFile"]:
"""Purge all files that no longer exist on s3."""
# if the last_bucket_sync timestamp wasn't updated,
# then the file has been deleted from s3, which must be reflected in the db.
Expand Down Expand Up @@ -297,7 +298,7 @@ def get_input_samples_metadata_file(
@classmethod
def get_input_library_metadata_files(
cls, project_id: str, *, bucket: str = settings.AWS_S3_INPUT_BUCKET_NAME
) -> Iterable[Self]:
) -> QuerySet[Self]:
return OriginalFile.objects.filter(
is_metadata=True,
project_id=project_id,
Expand Down
7 changes: 4 additions & 3 deletions api/scpca_portal/models/project.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import csv
from collections import Counter
from typing import Dict, Iterable, List
from typing import Dict, List

from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.db.models import Count, Q
from django.db.models.query import QuerySet

from typing_extensions import Self

Expand Down Expand Up @@ -111,7 +112,7 @@ def valid_download_configs(self) -> List[Dict]:
]

@property
def original_files(self) -> Iterable[OriginalFile]:
def original_files(self) -> QuerySet[OriginalFile]:
return OriginalFile.downloadable_objects.filter(
project_id=self.scpca_id, is_project_file=True
)
Expand All @@ -121,7 +122,7 @@ def original_file_paths(self) -> List[str]:
return sorted(self.original_files.values_list("s3_key", flat=True))

@property
def computed_files(self) -> Iterable[ComputedFile]:
def computed_files(self) -> QuerySet[ComputedFile]:
return self.project_computed_files.order_by("created_at")

@property
Expand Down