From f7d75cff33672334df4b599f59ac5156db314a8b Mon Sep 17 00:00:00 2001 From: Sunny Sun <38218185+sunnyosun@users.noreply.github.com> Date: Sun, 17 Nov 2024 13:57:16 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20`blank=3DTrue`=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .pre-commit-config.yaml | 14 +- clinicore/__init__.py | 2 + clinicore/migrations/0001_initial.py | 10 +- ...iosample_project_clinicaltrial_and_more.py | 2 +- ...ter_artifactbiosample_artifact_and_more.py | 865 ++++++++++++++++++ clinicore/models.py | 183 ++-- pyproject.toml | 2 +- 8 files changed, 964 insertions(+), 116 deletions(-) create mode 100644 clinicore/migrations/0007_alter_artifactbiosample_artifact_and_more.py diff --git a/.gitignore b/.gitignore index f48bd54..a47e5a1 100644 --- a/.gitignore +++ b/.gitignore @@ -106,4 +106,4 @@ docs/clinicore.* lamin_sphinx docs/conf.py _docs_tmp* -docs/test-clinicore/ +test-clinicore/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ceaf80e..f992759 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,12 +2,12 @@ fail_fast: false default_language_version: python: python3 default_stages: - - commit - - push + - pre-commit + - pre-push minimum_pre_commit_version: 2.12.0 repos: - repo: https://github.com/pre-commit/mirrors-prettier - rev: v4.0.0-alpha.4 + rev: v4.0.0-alpha.8 hooks: - id: prettier exclude: | @@ -15,7 +15,7 @@ repos: docs/changelog.md ) - repo: https://github.com/kynan/nbstripout - rev: 0.6.1 + rev: 0.8.0 hooks: - id: nbstripout exclude: | @@ -24,13 +24,13 @@ repos: docs/notes/ ) - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.7 + rev: v0.7.4 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --unsafe-fixes] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: detect-private-key - id: check-ast @@ -44,7 +44,7 @@ repos: - id: trailing-whitespace - id: check-case-conflict - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.13.0 hooks: - id: mypy args: [--no-strict-optional, --ignore-missing-imports] diff --git a/clinicore/__init__.py b/clinicore/__init__.py index 4d6b4f8..098313c 100644 --- a/clinicore/__init__.py +++ b/clinicore/__init__.py @@ -33,6 +33,8 @@ def __getattr__(name): if _check_instance_setup(): + import lamindb + del __getattr__ # delete so that imports work out from .models import ( Biosample, diff --git a/clinicore/migrations/0001_initial.py b/clinicore/migrations/0001_initial.py index f3809d1..f2f6fab 100644 --- a/clinicore/migrations/0001_initial.py +++ b/clinicore/migrations/0001_initial.py @@ -91,7 +91,7 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(lnschema_core.models.CanValidate, models.Model), + bases=(lnschema_core.models.CanCurate, models.Model), ), migrations.CreateModel( name="Medication", @@ -179,7 +179,7 @@ class Migration(migrations.Migration): bases=( models.Model, lnschema_core.models.HasParents, - lnschema_core.models.CanValidate, + lnschema_core.models.CanCurate, ), ), migrations.CreateModel( @@ -263,7 +263,7 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(lnschema_core.models.CanValidate, models.Model), + bases=(lnschema_core.models.CanCurate, models.Model), ), migrations.CreateModel( name="Project", @@ -316,7 +316,7 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(lnschema_core.models.CanValidate, models.Model), + bases=(lnschema_core.models.CanCurate, models.Model), ), migrations.CreateModel( name="Treatment", @@ -400,6 +400,6 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(lnschema_core.models.CanValidate, models.Model), + bases=(lnschema_core.models.CanCurate, models.Model), ), ] diff --git a/clinicore/migrations/0004_remove_biosample_project_clinicaltrial_and_more.py b/clinicore/migrations/0004_remove_biosample_project_clinicaltrial_and_more.py index 7fb7af3..b2a2afe 100644 --- a/clinicore/migrations/0004_remove_biosample_project_clinicaltrial_and_more.py +++ b/clinicore/migrations/0004_remove_biosample_project_clinicaltrial_and_more.py @@ -74,7 +74,7 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(lnschema_core.models.CanValidate, models.Model), + bases=(lnschema_core.models.CanCurate, models.Model), ), migrations.AddField( model_name="biosample", diff --git a/clinicore/migrations/0007_alter_artifactbiosample_artifact_and_more.py b/clinicore/migrations/0007_alter_artifactbiosample_artifact_and_more.py new file mode 100644 index 0000000..3e194c4 --- /dev/null +++ b/clinicore/migrations/0007_alter_artifactbiosample_artifact_and_more.py @@ -0,0 +1,865 @@ +# Generated by Django 5.2 on 2024-11-15 14:08 + +import bionty.ids +import django.db.models.deletion +import lnschema_core.fields +import lnschema_core.ids +import lnschema_core.models +import lnschema_core.users +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bionty", "0041_alter_artifactcellline_artifact_and_more"), + ("clinicore", "0006_artifactbiosample_artifactclinicaltrial_and_more"), + ( + "lnschema_core", + "0069_alter_artifact__accessor_alter_artifact__hash_type_and_more", + ), + ] + + operations = [ + migrations.AlterField( + model_name="artifactbiosample", + name="artifact", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="links_biosample", + to="lnschema_core.artifact", + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="biosample", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifact", + to="clinicore.biosample", + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="feature", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifactbiosample", + to="lnschema_core.feature", + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="feature_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="label_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactbiosample", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="artifact", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="links_clinical_trial", + to="lnschema_core.artifact", + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="clinicaltrial", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifact", + to="clinicore.clinicaltrial", + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="feature", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifactclinicaltrial", + to="lnschema_core.feature", + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="feature_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="label_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactclinicaltrial", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="artifact", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="links_medication", + to="lnschema_core.artifact", + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="artifactmedication", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="feature", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifactmedication", + to="lnschema_core.feature", + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="feature_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="label_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="medication", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifact", + to="clinicore.medication", + ), + ), + migrations.AlterField( + model_name="artifactmedication", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="artifact", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="links_patient", + to="lnschema_core.artifact", + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="artifactpatient", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="feature", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifactpatient", + to="lnschema_core.feature", + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="feature_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="label_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="patient", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifact", + to="clinicore.patient", + ), + ), + migrations.AlterField( + model_name="artifactpatient", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="artifact", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="links_treatment", + to="lnschema_core.artifact", + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="feature", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifacttreatment", + to="lnschema_core.feature", + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="feature_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="label_ref_is_name", + field=lnschema_core.fields.BooleanField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="artifacttreatment", + name="treatment", + field=lnschema_core.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="links_artifact", + to="clinicore.treatment", + ), + ), + migrations.AlterField( + model_name="biosample", + name="batch", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=60, null=True + ), + ), + migrations.AlterField( + model_name="biosample", + name="clinical_trial", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="biosamples", + to="clinicore.clinicaltrial", + ), + ), + migrations.AlterField( + model_name="biosample", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="biosample", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="biosample", + name="description", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="biosample", + name="name", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=255, null=True + ), + ), + migrations.AlterField( + model_name="biosample", + name="patient", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="biosamples", + to="clinicore.patient", + ), + ), + migrations.AlterField( + model_name="biosample", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="biosample", + name="uid", + field=lnschema_core.fields.CharField( + blank=True, + default=lnschema_core.ids.base62_12, + max_length=12, + unique=True, + ), + ), + migrations.AlterField( + model_name="biosample", + name="updated_at", + field=lnschema_core.fields.DateTimeField(auto_now=True, db_index=True), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="description", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="name", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=255 + ), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="objective", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="title", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="uid", + field=lnschema_core.fields.CharField( + blank=True, + default=lnschema_core.ids.base62_8, + max_length=8, + unique=True, + ), + ), + migrations.AlterField( + model_name="clinicaltrial", + name="updated_at", + field=lnschema_core.fields.DateTimeField(auto_now=True, db_index=True), + ), + migrations.AlterField( + model_name="medication", + name="abbr", + field=lnschema_core.fields.CharField( + blank=True, + db_index=True, + default=None, + max_length=32, + null=True, + unique=True, + ), + ), + migrations.AlterField( + model_name="medication", + name="chembl_id", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=32, null=True + ), + ), + migrations.AlterField( + model_name="medication", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="medication", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="medication", + name="description", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="medication", + name="name", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=256 + ), + ), + migrations.AlterField( + model_name="medication", + name="ontology_id", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=32, null=True + ), + ), + migrations.AlterField( + model_name="medication", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="medication", + name="source", + field=lnschema_core.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="bionty.source", + ), + ), + migrations.AlterField( + model_name="medication", + name="synonyms", + field=lnschema_core.fields.TextField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="medication", + name="uid", + field=lnschema_core.fields.CharField( + blank=True, default=bionty.ids.ontology, max_length=8, unique=True + ), + ), + migrations.AlterField( + model_name="medication", + name="updated_at", + field=lnschema_core.fields.DateTimeField(auto_now=True, db_index=True), + ), + migrations.AlterField( + model_name="patient", + name="age", + field=lnschema_core.fields.IntegerField( + blank=True, db_index=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="patient", + name="birth_date", + field=lnschema_core.fields.DateField( + blank=True, db_index=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="patient", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="patient", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="patient", + name="deceased", + field=lnschema_core.fields.BooleanField( + blank=True, db_index=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="patient", + name="deceased_date", + field=lnschema_core.fields.DateField( + blank=True, db_index=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="patient", + name="ethnicity", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="bionty.ethnicity", + ), + ), + migrations.AlterField( + model_name="patient", + name="gender", + field=lnschema_core.fields.CharField( + blank=True, + choices=[ + ("male", "Male"), + ("female", "Female"), + ("other", "Other"), + ("unknown", "Unknown"), + ], + db_index=True, + default=None, + max_length=10, + null=True, + ), + ), + migrations.AlterField( + model_name="patient", + name="name", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=255 + ), + ), + migrations.AlterField( + model_name="patient", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="patient", + name="uid", + field=lnschema_core.fields.CharField( + blank=True, + default=lnschema_core.ids.base62_12, + max_length=12, + unique=True, + ), + ), + migrations.AlterField( + model_name="patient", + name="updated_at", + field=lnschema_core.fields.DateTimeField(auto_now=True, db_index=True), + ), + migrations.AlterField( + model_name="treatment", + name="administered_datetime", + field=lnschema_core.fields.DateTimeField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="treatment", + name="created_at", + field=lnschema_core.fields.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AlterField( + model_name="treatment", + name="created_by", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.users.current_user_id, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.user", + ), + ), + migrations.AlterField( + model_name="treatment", + name="dosage", + field=lnschema_core.fields.FloatField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name="treatment", + name="dosage_unit", + field=lnschema_core.fields.CharField( + blank=True, default=None, max_length=32, null=True + ), + ), + migrations.AlterField( + model_name="treatment", + name="duration", + field=lnschema_core.fields.DurationField( + blank=True, default=None, null=True + ), + ), + migrations.AlterField( + model_name="treatment", + name="medication", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="clinicore.medication", + ), + ), + migrations.AlterField( + model_name="treatment", + name="name", + field=lnschema_core.fields.CharField( + blank=True, db_index=True, default=None, max_length=255 + ), + ), + migrations.AlterField( + model_name="treatment", + name="route", + field=lnschema_core.fields.CharField( + blank=True, default=None, max_length=32, null=True + ), + ), + migrations.AlterField( + model_name="treatment", + name="run", + field=lnschema_core.fields.ForeignKey( + blank=True, + default=lnschema_core.models.current_run, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="lnschema_core.run", + ), + ), + migrations.AlterField( + model_name="treatment", + name="site", + field=lnschema_core.fields.CharField( + blank=True, default=None, max_length=32, null=True + ), + ), + migrations.AlterField( + model_name="treatment", + name="status", + field=lnschema_core.fields.CharField( + blank=True, + choices=[ + ("in-progress", "In Progress"), + ("completed", "Completed"), + ("entered-in-error", "Entered in Error"), + ("stopped", "Stopped"), + ("on-hold", "On Hold"), + ("unknown", "Unknown"), + ("not-done", "Not Done"), + ], + default=None, + max_length=16, + null=True, + ), + ), + migrations.AlterField( + model_name="treatment", + name="uid", + field=lnschema_core.fields.CharField( + blank=True, + default=lnschema_core.ids.base62_12, + max_length=12, + unique=True, + ), + ), + migrations.AlterField( + model_name="treatment", + name="updated_at", + field=lnschema_core.fields.DateTimeField(auto_now=True, db_index=True), + ), + ] diff --git a/clinicore/models.py b/clinicore/models.py index 3b23a61..e016c0a 100644 --- a/clinicore/models.py +++ b/clinicore/models.py @@ -1,15 +1,27 @@ from __future__ import annotations -from typing import TYPE_CHECKING, overload +from datetime import datetime # noqa +from typing import overload from bionty import ids as bionty_ids from bionty.models import BioRecord, CellType, Disease, Ethnicity, Source, Tissue from django.db import models -from django.db.models import CASCADE, PROTECT, DurationField +from django.db.models import CASCADE, PROTECT from lnschema_core import ids +from lnschema_core.fields import ( + BooleanField, + CharField, + DateField, + DateTimeField, + DurationField, + FloatField, + ForeignKey, + IntegerField, + TextField, +) from lnschema_core.models import ( Artifact, - CanValidate, + CanCurate, Collection, Feature, LinkORM, @@ -18,11 +30,8 @@ TracksUpdates, ) -if TYPE_CHECKING: - from datetime import datetime - -class ClinicalTrial(Record, CanValidate, TracksRun, TracksUpdates): +class ClinicalTrial(Record, CanCurate, TracksRun, TracksUpdates): """Models a ClinicalTrials. Example: @@ -37,15 +46,15 @@ class Meta(Record.Meta, TracksRun.Meta, TracksUpdates.Meta): id: int = models.AutoField(primary_key=True) """Internal id, valid only in one DB instance.""" - uid: str = models.CharField(unique=True, max_length=8, default=ids.base62_8) + uid: str = CharField(unique=True, max_length=8, default=ids.base62_8) """Universal id, valid across DB instances.""" - name: str | None = models.CharField(max_length=255, default=None, db_index=True) + name: str | None = CharField(max_length=255, default=None, db_index=True) """ClinicalTrials.gov ID, the format is "NCT" followed by an 8-digit number.""" - title: str | None = models.TextField(null=True, default=None) + title: str | None = TextField(null=True, default=None) """Official title of the clinical trial.""" - objective: str | None = models.TextField(null=True, default=None) + objective: str | None = TextField(null=True, default=None) """Objective of the clinical trial.""" - description: str | None = models.TextField(null=True, default=None) + description: str | None = TextField(null=True, default=None) """Description of the clinical trial.""" collections: Collection = models.ManyToManyField( Collection, related_name="clinical_trials" @@ -59,24 +68,24 @@ class Meta(Record.Meta, TracksRun.Meta, TracksUpdates.Meta): class ArtifactClinicalTrial(Record, LinkORM, TracksRun): id: int = models.BigAutoField(primary_key=True) - artifact: Artifact = models.ForeignKey( + artifact: Artifact = ForeignKey( Artifact, CASCADE, related_name="links_clinical_trial" ) - clinicaltrial: ClinicalTrial = models.ForeignKey( + clinicaltrial: ClinicalTrial = ForeignKey( ClinicalTrial, PROTECT, related_name="links_artifact" ) - feature: Feature = models.ForeignKey( + feature: Feature = ForeignKey( Feature, PROTECT, null=True, default=None, related_name="links_artifactclinicaltrial", ) - label_ref_is_name: bool | None = models.BooleanField(null=True, default=None) - feature_ref_is_name: bool | None = models.BooleanField(null=True, default=None) + label_ref_is_name: bool | None = BooleanField(null=True, default=None) + feature_ref_is_name: bool | None = BooleanField(null=True, default=None) -class Biosample(Record, CanValidate, TracksRun, TracksUpdates): +class Biosample(Record, CanCurate, TracksRun, TracksUpdates): """Models a specimen derived from an patient, such as tissue, blood, or cells. Examples: @@ -88,23 +97,19 @@ class Biosample(Record, CanValidate, TracksRun, TracksUpdates): id: int = models.AutoField(primary_key=True) """Internal id, valid only in one DB instance.""" - uid: str = models.CharField(unique=True, max_length=12, default=ids.base62_12) + uid: str = CharField(unique=True, max_length=12, default=ids.base62_12) """Universal id, valid across DB instances.""" - name: str | None = models.CharField( - max_length=255, default=None, db_index=True, null=True - ) + name: str | None = CharField(max_length=255, default=None, db_index=True, null=True) """Name of the biosample.""" - batch: str | None = models.CharField( - max_length=60, default=None, null=True, db_index=True - ) + batch: str | None = CharField(max_length=60, default=None, null=True, db_index=True) """Batch label of the biosample.""" - description: str | None = models.TextField(null=True, default=None) + description: str | None = TextField(null=True, default=None) """Description of the biosample.""" - patient: Patient = models.ForeignKey( + patient: Patient = ForeignKey( "Patient", PROTECT, related_name="biosamples", null=True, default=None ) """Patient linked to the biosample.""" - clinical_trial: ClinicalTrial = models.ForeignKey( + clinical_trial: ClinicalTrial = ForeignKey( ClinicalTrial, PROTECT, related_name="biosamples", null=True, default=None ) """Clinical trial linked to the biosample.""" @@ -126,24 +131,20 @@ class Biosample(Record, CanValidate, TracksRun, TracksUpdates): class ArtifactBiosample(Record, LinkORM, TracksRun): id: int = models.BigAutoField(primary_key=True) - artifact: Artifact = models.ForeignKey( - Artifact, CASCADE, related_name="links_biosample" - ) - biosample: Biosample = models.ForeignKey( - Biosample, PROTECT, related_name="links_artifact" - ) - feature: Feature = models.ForeignKey( + artifact: Artifact = ForeignKey(Artifact, CASCADE, related_name="links_biosample") + biosample: Biosample = ForeignKey(Biosample, PROTECT, related_name="links_artifact") + feature: Feature = ForeignKey( Feature, PROTECT, null=True, default=None, related_name="links_artifactbiosample", ) - label_ref_is_name: bool | None = models.BooleanField(null=True, default=None) - feature_ref_is_name: bool | None = models.BooleanField(null=True, default=None) + label_ref_is_name: bool | None = BooleanField(null=True, default=None) + feature_ref_is_name: bool | None = BooleanField(null=True, default=None) -class Patient(Record, CanValidate, TracksRun, TracksUpdates): +class Patient(Record, CanCurate, TracksRun, TracksUpdates): """Models a patient in a clinical study. Examples: @@ -164,29 +165,23 @@ class Patient(Record, CanValidate, TracksRun, TracksUpdates): id: int = models.AutoField(primary_key=True) """Internal id, valid only in one DB instance.""" - uid: str = models.CharField(unique=True, max_length=12, default=ids.base62_12) + uid: str = CharField(unique=True, max_length=12, default=ids.base62_12) """Universal id, valid across DB instances. Use this field to model internal patient IDs.""" - name: str | None = models.CharField(max_length=255, default=None, db_index=True) + name: str | None = CharField(max_length=255, default=None, db_index=True) """Name of the patient.""" - age: int | None = models.IntegerField(null=True, default=None, db_index=True) + age: int | None = IntegerField(null=True, default=None, db_index=True) """Age of the patient.""" - gender: str | None = models.CharField( + gender: str | None = CharField( max_length=10, choices=GENDER_CHOICES, null=True, default=None, db_index=True ) """Gender of the patient.""" - ethnicity: Ethnicity = models.ForeignKey( - Ethnicity, PROTECT, null=True, default=None - ) + ethnicity: Ethnicity = ForeignKey(Ethnicity, PROTECT, null=True, default=None) """Ethnicity of the patient.""" - birth_date: datetime | None = models.DateField( - db_index=True, null=True, default=None - ) + birth_date: datetime | None = DateField(db_index=True, null=True, default=None) """Birth date of the patient.""" - deceased: bool | None = models.BooleanField(db_index=True, null=True, default=None) + deceased: bool | None = BooleanField(db_index=True, null=True, default=None) """Whether the patient is deceased.""" - deceased_date: datetime | None = models.DateField( - db_index=True, null=True, default=None - ) + deceased_date: datetime | None = DateField(db_index=True, null=True, default=None) """Date of death of the patient.""" artifacts: Artifact = models.ManyToManyField( Artifact, through="ArtifactPatient", related_name="patients" @@ -196,21 +191,17 @@ class Patient(Record, CanValidate, TracksRun, TracksUpdates): class ArtifactPatient(Record, LinkORM, TracksRun): id: int = models.BigAutoField(primary_key=True) - artifact: Artifact = models.ForeignKey( - Artifact, CASCADE, related_name="links_patient" - ) - patient: Patient = models.ForeignKey( - Patient, PROTECT, related_name="links_artifact" - ) - feature: Feature = models.ForeignKey( + artifact: Artifact = ForeignKey(Artifact, CASCADE, related_name="links_patient") + patient: Patient = ForeignKey(Patient, PROTECT, related_name="links_artifact") + feature: Feature = ForeignKey( Feature, PROTECT, null=True, default=None, related_name="links_artifactpatient", ) - label_ref_is_name: bool | None = models.BooleanField(null=True, default=None) - feature_ref_is_name: bool | None = models.BooleanField(null=True, default=None) + label_ref_is_name: bool | None = BooleanField(null=True, default=None) + feature_ref_is_name: bool | None = BooleanField(null=True, default=None) class Medication(BioRecord, TracksRun, TracksUpdates): @@ -225,25 +216,25 @@ class Meta(BioRecord.Meta, TracksRun.Meta, TracksUpdates.Meta): id: int = models.AutoField(primary_key=True) """Internal id, valid only in one DB instance.""" - uid: str = models.CharField(unique=True, max_length=8, default=bionty_ids.ontology) + uid: str = CharField(unique=True, max_length=8, default=bionty_ids.ontology) """A universal id (hash of selected field).""" - name: str = models.CharField(max_length=256, db_index=True) + name: str = CharField(max_length=256, db_index=True) """Name of the medication.""" - ontology_id: str | None = models.CharField( + ontology_id: str | None = CharField( max_length=32, db_index=True, null=True, default=None ) """Ontology ID of the medication.""" - chembl_id: str | None = models.CharField( + chembl_id: str | None = CharField( max_length=32, db_index=True, null=True, default=None ) """ChEMBL ID of the medication.""" - abbr: str | None = models.CharField( + abbr: str | None = CharField( max_length=32, db_index=True, unique=True, null=True, default=None ) """A unique abbreviation of medication.""" - synonyms: str | None = models.TextField(null=True, default=None) + synonyms: str | None = TextField(null=True, default=None) """Bar-separated (|) synonyms that correspond to this medication.""" - description: str | None = models.TextField(null=True, default=None) + description: str | None = TextField(null=True, default=None) """Description of the medication.""" parents: Medication = models.ManyToManyField( "self", symmetrical=False, related_name="children" @@ -264,15 +255,13 @@ def __init__( description: str | None, parents: list[Medication], source: Source | None, - ): - ... + ): ... @overload def __init__( self, *db_args, - ): - ... + ): ... def __init__( self, @@ -284,24 +273,22 @@ def __init__( class ArtifactMedication(Record, LinkORM, TracksRun): id: int = models.BigAutoField(primary_key=True) - artifact: Artifact = models.ForeignKey( - Artifact, CASCADE, related_name="links_medication" - ) - medication: Medication = models.ForeignKey( + artifact: Artifact = ForeignKey(Artifact, CASCADE, related_name="links_medication") + medication: Medication = ForeignKey( Medication, PROTECT, related_name="links_artifact" ) - feature: Feature = models.ForeignKey( + feature: Feature = ForeignKey( Feature, PROTECT, null=True, default=None, related_name="links_artifactmedication", ) - label_ref_is_name: bool | None = models.BooleanField(null=True, default=None) - feature_ref_is_name: bool | None = models.BooleanField(null=True, default=None) + label_ref_is_name: bool | None = BooleanField(null=True, default=None) + feature_ref_is_name: bool | None = BooleanField(null=True, default=None) -class Treatment(Record, CanValidate, TracksRun, TracksUpdates): +class Treatment(Record, CanCurate, TracksRun, TracksUpdates): """Models compound treatments such as drugs. Examples: @@ -322,31 +309,29 @@ class Treatment(Record, CanValidate, TracksRun, TracksUpdates): id: int = models.AutoField(primary_key=True) """Internal id, valid only in one DB instance.""" - uid: str = models.CharField(unique=True, max_length=12, default=ids.base62_12) + uid: str = CharField(unique=True, max_length=12, default=ids.base62_12) """Universal id, valid across DB instances.""" - name: str | None = models.CharField(max_length=255, default=None, db_index=True) + name: str | None = CharField(max_length=255, default=None, db_index=True) """Name of the treatment.""" - status: str | None = models.CharField( + status: str | None = CharField( max_length=16, choices=STATUS_CHOICES, null=True, default=None ) """Status of the treatment.""" - medication: Medication | None = models.ForeignKey( + medication: Medication | None = ForeignKey( Medication, PROTECT, null=True, default=None ) """Medications linked to the treatment.""" - dosage: float | None = models.FloatField(null=True, default=None) + dosage: float | None = FloatField(null=True, default=None) """Dosage of the treatment.""" - dosage_unit: str | None = models.CharField(max_length=32, null=True, default=None) + dosage_unit: str | None = CharField(max_length=32, null=True, default=None) """Unit of the dosage.""" - administered_datetime: datetime | None = models.DateTimeField( - null=True, default=None - ) + administered_datetime: datetime | None = DateTimeField(null=True, default=None) """Date and time the treatment was administered.""" - duration: DurationField = models.DurationField(null=True, default=None) + duration: DurationField = DurationField(null=True, default=None) """Duration of the treatment.""" - route: str | None = models.CharField(max_length=32, null=True, default=None) + route: str | None = CharField(max_length=32, null=True, default=None) """Route of administration of the treatment.""" - site: str | None = models.CharField(max_length=32, null=True, default=None) + site: str | None = CharField(max_length=32, null=True, default=None) """Body site of administration of the treatment.""" artifacts: Artifact = models.ManyToManyField( Artifact, through="ArtifactTreatment", related_name="treatments" @@ -356,18 +341,14 @@ class Treatment(Record, CanValidate, TracksRun, TracksUpdates): class ArtifactTreatment(Record, LinkORM, TracksRun): id: int = models.BigAutoField(primary_key=True) - artifact: Artifact = models.ForeignKey( - Artifact, CASCADE, related_name="links_treatment" - ) - treatment: Treatment = models.ForeignKey( - Treatment, PROTECT, related_name="links_artifact" - ) - feature: Feature = models.ForeignKey( + artifact: Artifact = ForeignKey(Artifact, CASCADE, related_name="links_treatment") + treatment: Treatment = ForeignKey(Treatment, PROTECT, related_name="links_artifact") + feature: Feature = ForeignKey( Feature, PROTECT, null=True, default=None, related_name="links_artifacttreatment", ) - label_ref_is_name: bool | None = models.BooleanField(null=True, default=None) - feature_ref_is_name: bool | None = models.BooleanField(null=True, default=None) + label_ref_is_name: bool | None = BooleanField(null=True, default=None) + feature_ref_is_name: bool | None = BooleanField(null=True, default=None) diff --git a/pyproject.toml b/pyproject.toml index ee85935..94ed546 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,7 +116,7 @@ ignore = [ # subprocess` call: check for execution of untrusted input - https://github.com/PyCQA/bandit/issues/333 "S603", # Starting a process with a partial executable path - "S607" + "S607", ] [tool.ruff.pydocstyle]