nci-cidc-api-modules 1.2.0__py3-none-any.whl → 1.2.2__py3-none-any.whl
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.
- cidc_api/config/db.py +5 -33
- cidc_api/models/files/facets.py +5 -0
- cidc_api/models/models.py +39 -3
- {nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/METADATA +24 -24
- {nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/RECORD +8 -8
- {nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/WHEEL +0 -0
- {nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/licenses/LICENSE +0 -0
- {nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/top_level.txt +0 -0
cidc_api/config/db.py
CHANGED
@@ -45,33 +45,7 @@ def get_sqlalchemy_database_uri(testing: bool = False) -> str:
|
|
45
45
|
# Connect to the test database
|
46
46
|
db_uri = environ.get("TEST_POSTGRES_URI", "fake-conn-string")
|
47
47
|
elif not db_uri:
|
48
|
-
|
49
|
-
# db_uri = f"postgresql+pg8000://{environ.get('CLOUD_SQL_DB_USER')}:xxx@/{environ.get('CLOUD_SQL_DB_NAME')}"
|
50
|
-
|
51
|
-
secrets = get_secrets_manager(testing)
|
52
|
-
|
53
|
-
# If POSTGRES_URI env variable is not set,
|
54
|
-
# we're connecting to a Cloud SQL instance.
|
55
|
-
|
56
|
-
config: dict = {
|
57
|
-
"drivername": "postgresql",
|
58
|
-
"username": environ.get("CLOUD_SQL_DB_USER"),
|
59
|
-
"password": secrets.get(environ.get("CLOUD_SQL_DB_PASS_ID")),
|
60
|
-
"database": environ.get("CLOUD_SQL_DB_NAME"),
|
61
|
-
}
|
62
|
-
|
63
|
-
if environ.get("CLOUD_SQL_INSTANCE_NAME"):
|
64
|
-
socket_dir = environ.get("CLOUD_SQL_SOCKET_DIR", "/cloudsql/")
|
65
|
-
|
66
|
-
# If CLOUD_SQL_INSTANCE_NAME is defined, we're connecting
|
67
|
-
# via a unix socket from inside App Engine.
|
68
|
-
config["query"] = {"host": f'{socket_dir}{environ.get("CLOUD_SQL_INSTANCE_NAME")}'}
|
69
|
-
else:
|
70
|
-
raise RuntimeError(
|
71
|
-
"Either POSTGRES_URI or CLOUD_SQL_INSTANCE_NAME must be defined to connect " + "to a database."
|
72
|
-
)
|
73
|
-
|
74
|
-
db_uri = str(URL.create(**config).render_as_string(hide_password=False))
|
48
|
+
db_uri = f"postgresql+pg8000://{environ.get('CLOUD_SQL_DB_USER')}:xxx@/{environ.get('CLOUD_SQL_DB_NAME')}"
|
75
49
|
|
76
50
|
assert db_uri
|
77
51
|
|
@@ -80,9 +54,7 @@ def get_sqlalchemy_database_uri(testing: bool = False) -> str:
|
|
80
54
|
|
81
55
|
# Use SQLALCHEMY_ENGINE_OPTIONS to connect to the cloud but use uri for local db
|
82
56
|
def cloud_connector(testing: bool = False):
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
# else:
|
88
|
-
# return {}
|
57
|
+
if not testing and not environ.get("POSTGRES_URI"):
|
58
|
+
return {"creator": getconn}
|
59
|
+
else:
|
60
|
+
return {}
|
cidc_api/models/files/facets.py
CHANGED
@@ -361,6 +361,11 @@ assay_facets: Facets = {
|
|
361
361
|
"colorized image": FacetConfig(["/visium/colorized.tiff"]),
|
362
362
|
"cytassist image": FacetConfig(["/visium/cytassist.tiff"]),
|
363
363
|
},
|
364
|
+
"NULISA": {
|
365
|
+
"Metadata": FacetConfig(["/nulisa/metadata.csv", "Metadata for NULISA run"]),
|
366
|
+
"NPQ File": FacetConfig(["/nulisa/npq_file.csv", "NPQ file for NULISA run"]),
|
367
|
+
"Raw Counts File": FacetConfig(["/nulisa/raw_counts_file.csv", "Raw counts file for NULISA run"]),
|
368
|
+
},
|
364
369
|
"mIHC": {
|
365
370
|
"Samples Report": FacetConfig(["/mihc/sample_report.csv"], "Samples report for mIHC run"),
|
366
371
|
"Multitiffs": FacetConfig(["/mihc/multitiffs.tar.gz"], "Multi Tiffs file from mIHC run"),
|
cidc_api/models/models.py
CHANGED
@@ -531,6 +531,7 @@ class IAMException(Exception):
|
|
531
531
|
EXTRA_DATA_TYPES = [
|
532
532
|
"participants info",
|
533
533
|
"samples info",
|
534
|
+
"clinical_upload",
|
534
535
|
"file_group",
|
535
536
|
]
|
536
537
|
ALL_UPLOAD_TYPES = set(
|
@@ -3117,7 +3118,7 @@ class DownloadableFiles(CommonColumns):
|
|
3117
3118
|
cls.file_purpose.label(purp_col.key),
|
3118
3119
|
func.json_agg(cls.id).label(ids_col.key),
|
3119
3120
|
)
|
3120
|
-
.group_by(cls.trial_id,
|
3121
|
+
.group_by(cls.trial_id, type_col, purp_col)
|
3121
3122
|
.alias("id_bundles")
|
3122
3123
|
)
|
3123
3124
|
purpose_bundles = (
|
@@ -3497,11 +3498,33 @@ class IngestionJobs(CommonColumns):
|
|
3497
3498
|
.first()
|
3498
3499
|
)
|
3499
3500
|
|
3500
|
-
# TODO: figure out which users have access to which jobs
|
3501
3501
|
@classmethod
|
3502
3502
|
@with_default_session
|
3503
3503
|
def get_open_jobs_for_user(cls, user: Users, session: Session = None) -> list["IngestionJobs"]:
|
3504
|
-
|
3504
|
+
if user.role not in [CIDCRole.ADMIN.value, CIDCRole.CLINICAL_TRIAL_USER.value]:
|
3505
|
+
return []
|
3506
|
+
job_query = session.query(cls).filter(cls.status.notin_(["DRAFT"]))
|
3507
|
+
if (
|
3508
|
+
user.role != CIDCRole.ADMIN.value
|
3509
|
+
and not session.query(Permissions)
|
3510
|
+
.filter(
|
3511
|
+
Permissions.granted_to_user == user.id,
|
3512
|
+
Permissions.upload_type == "clinical_upload",
|
3513
|
+
Permissions.trial_id == Permissions.EVERY,
|
3514
|
+
)
|
3515
|
+
.all()
|
3516
|
+
):
|
3517
|
+
authorized_trials = (
|
3518
|
+
session.query(Permissions)
|
3519
|
+
.filter(
|
3520
|
+
Permissions.granted_to_user == user.id,
|
3521
|
+
Permissions.upload_type == "clinical_upload",
|
3522
|
+
Permissions.trial_id != Permissions.EVERY,
|
3523
|
+
)
|
3524
|
+
.all()
|
3525
|
+
)
|
3526
|
+
job_query = job_query.filter(cls.trial_id.in_(map(lambda x: x.trial_id, authorized_trials)))
|
3527
|
+
return job_query.order_by(cls._created.desc()).all()
|
3505
3528
|
|
3506
3529
|
|
3507
3530
|
class JobFileCategories(CommonColumns):
|
@@ -3571,3 +3594,16 @@ class FileValidationErrors(CommonColumns):
|
|
3571
3594
|
new_error = FileValidationErrors(file_id=file_id, job_id=job_id, error_message=error_message, location=location)
|
3572
3595
|
new_error.insert(session=session)
|
3573
3596
|
return new_error
|
3597
|
+
|
3598
|
+
@classmethod
|
3599
|
+
@with_default_session
|
3600
|
+
def delete_by_file_ids(cls, file_ids: list[int], session: Session = None):
|
3601
|
+
"""Delete all validation errors for the given list of file_ids."""
|
3602
|
+
if file_ids:
|
3603
|
+
session.query(cls).filter(cls.file_id.in_(file_ids)).delete(synchronize_session=False)
|
3604
|
+
session.commit()
|
3605
|
+
|
3606
|
+
@classmethod
|
3607
|
+
@with_default_session
|
3608
|
+
def get_errors_for_job_sorted_by_file_id(cls, job_id: int, session: Session = None) -> list["FileValidationErrors"]:
|
3609
|
+
return session.query(cls).filter(cls.job_id == job_id).order_by(cls.file_id.asc()).all()
|
@@ -1,35 +1,35 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nci_cidc_api_modules
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.2
|
4
4
|
Summary: SQLAlchemy data models and configuration tools used in the NCI CIDC API
|
5
5
|
Home-page: https://github.com/NCI-CIDC/cidc-api-gae
|
6
6
|
License: MIT license
|
7
7
|
Requires-Python: >=3.13
|
8
8
|
Description-Content-Type: text/markdown
|
9
9
|
License-File: LICENSE
|
10
|
-
Requires-Dist: werkzeug
|
11
|
-
Requires-Dist: flask
|
12
|
-
Requires-Dist: flask-migrate
|
13
|
-
Requires-Dist: flask-sqlalchemy
|
14
|
-
Requires-Dist: sqlalchemy
|
15
|
-
Requires-Dist: marshmallow
|
16
|
-
Requires-Dist: marshmallow-sqlalchemy
|
17
|
-
Requires-Dist: google-cloud-storage
|
18
|
-
Requires-Dist: google-cloud-secret-manager
|
19
|
-
Requires-Dist: google-cloud-pubsub
|
20
|
-
Requires-Dist: google-cloud-bigquery
|
21
|
-
Requires-Dist: google-api-python-client
|
22
|
-
Requires-Dist: google-auth
|
23
|
-
Requires-Dist: packaging
|
24
|
-
Requires-Dist: pyarrow
|
25
|
-
Requires-Dist: numpy
|
26
|
-
Requires-Dist: pandas
|
27
|
-
Requires-Dist: python-dotenv
|
28
|
-
Requires-Dist: requests
|
29
|
-
Requires-Dist: jinja2
|
30
|
-
Requires-Dist: certifi
|
31
|
-
Requires-Dist: cloud-sql-python-connector[pg8000]
|
32
|
-
Requires-Dist: nci-cidc-schemas==0.28.
|
10
|
+
Requires-Dist: werkzeug>=3.1.3
|
11
|
+
Requires-Dist: flask>=3.1.2
|
12
|
+
Requires-Dist: flask-migrate>=4.1.0
|
13
|
+
Requires-Dist: flask-sqlalchemy>=3.1.1
|
14
|
+
Requires-Dist: sqlalchemy>=2.0.43
|
15
|
+
Requires-Dist: marshmallow>=4.0.0
|
16
|
+
Requires-Dist: marshmallow-sqlalchemy>=1.4.2
|
17
|
+
Requires-Dist: google-cloud-storage>=3.3.0
|
18
|
+
Requires-Dist: google-cloud-secret-manager>=2.24.0
|
19
|
+
Requires-Dist: google-cloud-pubsub>=2.31.1
|
20
|
+
Requires-Dist: google-cloud-bigquery>=3.36.0
|
21
|
+
Requires-Dist: google-api-python-client>=2.179.0
|
22
|
+
Requires-Dist: google-auth>=2.40.3
|
23
|
+
Requires-Dist: packaging>=25.0
|
24
|
+
Requires-Dist: pyarrow>=21.0.0
|
25
|
+
Requires-Dist: numpy>=2.3.2
|
26
|
+
Requires-Dist: pandas>=2.3.1
|
27
|
+
Requires-Dist: python-dotenv>=1.1.1
|
28
|
+
Requires-Dist: requests>=2.32.5
|
29
|
+
Requires-Dist: jinja2>=3.1.6
|
30
|
+
Requires-Dist: certifi>=2025.8.3
|
31
|
+
Requires-Dist: cloud-sql-python-connector[pg8000]>=1.18.4
|
32
|
+
Requires-Dist: nci-cidc-schemas==0.28.3
|
33
33
|
Dynamic: description
|
34
34
|
Dynamic: description-content-type
|
35
35
|
Dynamic: home-page
|
@@ -1,15 +1,15 @@
|
|
1
1
|
cidc_api/config/__init__.py,sha256=5mX8GAPxUKV84iS-aGOoE-4m68LsOCGCDptXNdlgvj0,148
|
2
|
-
cidc_api/config/db.py,sha256=
|
2
|
+
cidc_api/config/db.py,sha256=eFCkJDeykRIJZ25kePVjRNrZcrcKTc1s2K0yErr46LI,1683
|
3
3
|
cidc_api/config/logging.py,sha256=abhVYtn8lfhIt0tyV2WHFgSmp_s2eeJh7kodB6LH4J0,1149
|
4
4
|
cidc_api/config/secrets.py,sha256=jRFj7W43pWuPf9DZQLCKF7WPXf5cUv-BAaS3ASqhV_Q,1481
|
5
5
|
cidc_api/config/settings.py,sha256=NsJbqW6Vqcz2f79xcAbk4th5tHne_I-RPCbKq_3hpz0,4427
|
6
6
|
cidc_api/models/__init__.py,sha256=bl445G8Zic9YbhZ8ZBni07wtBMhLJRMBA-JqjLxx2bw,66
|
7
7
|
cidc_api/models/migrations.py,sha256=gp9vtkYbA9FFy2s-7woelAmsvQbJ41LO2_DY-YkFIrQ,11464
|
8
|
-
cidc_api/models/models.py,sha256=
|
8
|
+
cidc_api/models/models.py,sha256=tpEprnBbvhTCBPTouKvctTrCtOoiyJ3R-FFy8zXQpAI,145600
|
9
9
|
cidc_api/models/schemas.py,sha256=6IE2dJoEMcMbi0Vr1V3cYKnPKU0hv9vRKBixOZHe88s,2766
|
10
10
|
cidc_api/models/files/__init__.py,sha256=8BMTnUSHzUbz0lBeEQY6NvApxDD3GMWMduoVMos2g4Y,213
|
11
11
|
cidc_api/models/files/details.py,sha256=sZkGM7iEV4-J6IDQCdiMV6KBDLbPxCOqUMaU3aY9rX8,65153
|
12
|
-
cidc_api/models/files/facets.py,sha256=
|
12
|
+
cidc_api/models/files/facets.py,sha256=bJChPlBHYJuDFgV1eMZkqyXE8sej7jRk2sQ2kNgE9m4,32620
|
13
13
|
cidc_api/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
14
|
cidc_api/shared/auth.py,sha256=PHqmVGkqDjbmUofytVFwD_9ssgUomESl3fFtFHPwZYQ,9062
|
15
15
|
cidc_api/shared/emails.py,sha256=HQIixEUsR8yyu7Iv8S81RjtvEQeGuzQHzBfGsWIfP7k,4961
|
@@ -17,8 +17,8 @@ cidc_api/shared/file_handling.py,sha256=l4wiRkVJLL7QbCoODsLx-uki6Km8QoMmUlRVnUV9
|
|
17
17
|
cidc_api/shared/gcloud_client.py,sha256=ETQ34qKtO7l0svVhiHXxXewiyNjwIMgoeVcqrg-Twtk,36902
|
18
18
|
cidc_api/shared/jose.py,sha256=-qzGzEDAlokEp9E7WtBtQkXyyfPWTYXlwYpCqVJWmqM,1830
|
19
19
|
cidc_api/shared/rest_utils.py,sha256=RwR30WOUAYCxL7V-i2totEyeriG30GbBDvBcpLXhM9w,6594
|
20
|
-
nci_cidc_api_modules-1.2.
|
21
|
-
nci_cidc_api_modules-1.2.
|
22
|
-
nci_cidc_api_modules-1.2.
|
23
|
-
nci_cidc_api_modules-1.2.
|
24
|
-
nci_cidc_api_modules-1.2.
|
20
|
+
nci_cidc_api_modules-1.2.2.dist-info/licenses/LICENSE,sha256=pNYWVTHaYonnmJyplmeAp7tQAjosmDpAWjb34jjv7Xs,1102
|
21
|
+
nci_cidc_api_modules-1.2.2.dist-info/METADATA,sha256=7SGLnfh5Yc0j_AgRQ1eh0VetOL5MVh_d0uOah5_C5Bw,39537
|
22
|
+
nci_cidc_api_modules-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
nci_cidc_api_modules-1.2.2.dist-info/top_level.txt,sha256=rNiRzL0lJGi5Q9tY9uSoMdTbJ-7u5c_D2E86KA94yRA,9
|
24
|
+
nci_cidc_api_modules-1.2.2.dist-info/RECORD,,
|
File without changes
|
{nci_cidc_api_modules-1.2.0.dist-info → nci_cidc_api_modules-1.2.2.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
File without changes
|