nci-cidc-api-modules 1.0.0__py3-none-any.whl → 1.0.1__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/shared/auth.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from functools import wraps
2
- from packaging import version
3
2
  from typing import List
4
3
 
5
4
  import requests
5
+ from packaging import version
6
6
  from jose import jwt
7
7
  from flask import g, request, current_app as app, Flask
8
8
  from werkzeug.exceptions import Unauthorized, BadRequest, PreconditionFailed
@@ -13,6 +13,8 @@ from ..config.logging import get_logger
13
13
 
14
14
  logger = get_logger(__name__)
15
15
 
16
+ TIMEOUT_IN_SECONDS = 20
17
+
16
18
 
17
19
  ### Main auth utility functions ###
18
20
  def validate_api_auth(app: Flask):
@@ -32,7 +34,7 @@ def validate_api_auth(app: Flask):
32
34
  )
33
35
 
34
36
 
35
- def requires_auth(resource: str, allowed_roles: list = []):
37
+ def requires_auth(resource: str, allowed_roles: list = None):
36
38
  """
37
39
  A decorator that adds authentication and basic access to an endpoint.
38
40
 
@@ -43,6 +45,9 @@ def requires_auth(resource: str, allowed_roles: list = []):
43
45
  Unauthorized if unauthorized
44
46
  """
45
47
 
48
+ if allowed_roles is None:
49
+ allowed_roles = []
50
+
46
51
  def decorator(endpoint):
47
52
  # Store metadata on this function stating that it is protected by authentication
48
53
  endpoint.is_protected = True
@@ -159,11 +164,11 @@ def _extract_token() -> str:
159
164
  assert bearer.lower() == "bearer"
160
165
  else:
161
166
  id_token = request.json["id_token"]
162
- except (AssertionError, AttributeError, KeyError, TypeError, ValueError):
167
+ except (AssertionError, AttributeError, KeyError, TypeError, ValueError) as exc:
163
168
  raise Unauthorized(
164
169
  "Either the 'Authorization' header must be set with structure 'Authorization: Bearer <id token>' "
165
170
  'or "id_token" must be present in the JSON body of the request.'
166
- )
171
+ ) from exc
167
172
 
168
173
  return id_token
169
174
 
@@ -184,11 +189,11 @@ def _get_issuer_public_key(token: str) -> dict:
184
189
  try:
185
190
  header = jwt.get_unverified_header(token)
186
191
  except jwt.JWTError as e:
187
- raise Unauthorized(str(e))
192
+ raise Unauthorized(str(e)) from e
188
193
 
189
194
  # Get public keys from our Auth0 domain
190
195
  jwks_url = f"https://{AUTH0_DOMAIN}/.well-known/jwks.json"
191
- jwks = requests.get(jwks_url).json()
196
+ jwks = requests.get(jwks_url, timeout=TIMEOUT_IN_SECONDS).json()
192
197
 
193
198
  # Obtain the public key used to sign this token
194
199
  public_key = None
@@ -198,7 +203,7 @@ def _get_issuer_public_key(token: str) -> dict:
198
203
 
199
204
  # If no matching public key was found, we can't validate the token
200
205
  if not public_key:
201
- raise Unauthorized("Found no public key with id %s" % header["kid"])
206
+ raise Unauthorized(f"Found no public key with id {header['kid']}")
202
207
 
203
208
  return public_key
204
209
 
@@ -233,11 +238,11 @@ def _decode_id_token(token: str, public_key: dict) -> dict:
233
238
  except jwt.ExpiredSignatureError as e:
234
239
  raise Unauthorized(
235
240
  f"{e} Token expired. Obtain a new login token from the CIDC Portal, then try logging in again."
236
- )
241
+ ) from e
237
242
  except jwt.JWTClaimsError as e:
238
- raise Unauthorized(str(e))
243
+ raise Unauthorized(str(e)) from e
239
244
  except jwt.JWTError as e:
240
- raise Unauthorized(str(e))
245
+ raise Unauthorized(str(e)) from e
241
246
 
242
247
  # Currently, only id_tokens are accepted for authentication.
243
248
  # Going forward, we could also accept access tokens that we
@@ -340,9 +345,9 @@ def _enforce_cli_version():
340
345
 
341
346
  try:
342
347
  client, client_version = user_agent.split("/", 1)
343
- except ValueError:
344
- logger.error(f"Unrecognized user-agent string format: {user_agent}")
345
- raise BadRequest("could not parse User-Agent string")
348
+ except ValueError as exc:
349
+ logger.error("Unrecognized user-agent string format: %s", user_agent)
350
+ raise BadRequest("could not parse User-Agent string") from exc
346
351
 
347
352
  # The CLI sets the User-Agent header to `cidc-cli/{version}`,
348
353
  # so we can assess whether the requester needs to update their CLI.
@@ -1,23 +1,21 @@
1
1
  """Utilities for interacting with the Google Cloud Platform APIs."""
2
+
3
+ # pylint: disable=logging-fstring-interpolation
4
+
2
5
  import json
3
6
  import os
4
7
  from os import environ
5
-
6
- from cidc_api.config.secrets import get_secrets_manager
7
-
8
- os.environ["TZ"] = "UTC"
8
+ import base64
9
9
  import datetime
10
10
  import warnings
11
11
  import hashlib
12
12
  from collections import namedtuple
13
13
  from concurrent.futures import Future
14
- from sqlalchemy.orm.session import Session
15
14
  from typing import (
16
15
  Any,
17
16
  BinaryIO,
18
17
  Callable,
19
18
  Dict,
20
- Iterable,
21
19
  List,
22
20
  Optional,
23
21
  Set,
@@ -25,15 +23,18 @@ from typing import (
25
23
  Union,
26
24
  )
27
25
 
28
- import requests
26
+ from werkzeug.datastructures import FileStorage
27
+ from sqlalchemy.orm.session import Session
29
28
  from google.cloud import storage, pubsub, bigquery
30
29
  from google.cloud.bigquery.enums import EntityTypes
31
30
  from google.oauth2.service_account import Credentials
32
- from google.auth.credentials import AnonymousCredentials
33
- from werkzeug.datastructures import FileStorage
34
- import googleapiclient.discovery
35
31
  from google.api_core.iam import Policy
36
32
  from google.api_core.client_options import ClientOptions
33
+ import googleapiclient.discovery
34
+ import requests
35
+
36
+ from cidc_schemas.prism.constants import ASSAY_TO_FILEPATH
37
+ from cidc_api.config.secrets import get_secrets_manager
37
38
 
38
39
  from ..config.settings import (
39
40
  DEV_USE_GCS,
@@ -57,42 +58,43 @@ from ..config.settings import (
57
58
  )
58
59
  from ..config.logging import get_logger
59
60
 
60
- from cidc_schemas.prism.constants import ASSAY_TO_FILEPATH
61
-
61
+ os.environ["TZ"] = "UTC"
62
62
  logger = get_logger(__name__)
63
63
 
64
- _storage_client = None
65
- _bigquery_client = None
66
- _crm_service = None
64
+ TIMEOUT_IN_SECONDS = 20
65
+
66
+ # these should be initialized here or used as cached values
67
+ STORAGE_CLIENT = None
68
+ BIGQUERY_CLIENT = None
69
+ CRM_SERVICE = None
67
70
 
68
71
  # The Secret Manager object should only be initiated once and reused.
69
72
  # This is due to the fact that every time this object is initiated, a
70
73
  # Google Cloud client is also initiated, which is an expensive handshake
71
74
  # that significantly adds to the latency of the script.
72
- if not TESTING:
73
- secret_manager = get_secrets_manager()
75
+ SECRET_MANAGER = get_secrets_manager(TESTING)
74
76
 
75
77
 
76
78
  def _get_storage_client() -> storage.Client:
77
- global _storage_client
78
- if _storage_client is None:
79
+ global STORAGE_CLIENT
80
+ if STORAGE_CLIENT is None:
79
81
  logger.debug("Getting local client")
80
82
  if os.environ.get("DEV_GOOGLE_STORAGE", None):
81
- secret_manager = get_secrets_manager()
82
83
  client_options = ClientOptions(
83
84
  api_endpoint=os.environ.get("DEV_GOOGLE_STORAGE")
84
85
  )
85
86
  credentials = Credentials.from_service_account_info(
86
- json.loads(secret_manager.get("APP_ENGINE_CREDENTIALS"))
87
+ json.loads(SECRET_MANAGER.get("APP_ENGINE_CREDENTIALS"))
87
88
  )
88
- _storage_client = storage.Client(
89
+ STORAGE_CLIENT = storage.Client(
89
90
  client_options=client_options, credentials=credentials
90
91
  )
91
- logger.debug(f"Local client set to {_storage_client}")
92
- return _storage_client
93
- else:
94
- return _get_storage_client2()
95
- return _storage_client
92
+ logger.debug(f"Local client set to {STORAGE_CLIENT}")
93
+ return STORAGE_CLIENT
94
+
95
+ return _get_storage_client2()
96
+
97
+ return STORAGE_CLIENT
96
98
 
97
99
 
98
100
  def _get_storage_client2() -> storage.Client:
@@ -102,36 +104,36 @@ def _get_storage_client2() -> storage.Client:
102
104
 
103
105
  directly providing service account credentials for signing in get_signed_url() below
104
106
  """
105
- global _storage_client
106
- if _storage_client is None:
107
+ global STORAGE_CLIENT
108
+ if STORAGE_CLIENT is None:
107
109
  credentials = Credentials.from_service_account_info(
108
- json.loads(secret_manager.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
110
+ json.loads(SECRET_MANAGER.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
109
111
  )
110
112
  # client_options = ClientOptions(api_endpoint=os.environ.get("DEV_GOOGLE_STORAGE"))
111
- # _storage_client = storage.Client(client_options=client_options, credentials=credentials)
112
- _storage_client = storage.Client(credentials=credentials)
113
- return _storage_client
113
+ # STORAGE_CLIENT = storage.Client(client_options=client_options, credentials=credentials)
114
+ STORAGE_CLIENT = storage.Client(credentials=credentials)
115
+ return STORAGE_CLIENT
114
116
 
115
117
 
116
118
  def _get_crm_service() -> googleapiclient.discovery.Resource:
117
119
  """
118
120
  Initializes a Cloud Resource Manager service.
119
121
  """
120
- global _crm_service
121
- if _crm_service is None:
122
+ global CRM_SERVICE
123
+ if CRM_SERVICE is None:
122
124
  credentials = Credentials.from_service_account_info(
123
- json.loads(secret_manager.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
125
+ json.loads(SECRET_MANAGER.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
124
126
  )
125
- _crm_service = googleapiclient.discovery.build(
127
+ CRM_SERVICE = googleapiclient.discovery.build(
126
128
  "cloudresourcemanager", "v1", credentials=credentials
127
129
  )
128
- return _crm_service
130
+ return CRM_SERVICE
129
131
 
130
132
 
131
133
  def _get_bucket(bucket_name: str) -> storage.Bucket:
132
134
  """
133
135
  Get the bucket with name `bucket_name` from GCS.
134
- This does not make an HTTP request; it simply instantiates a bucket object owned by _storage_client.
136
+ This does not make an HTTP request; it simply instantiates a bucket object owned by STORAGE_CLIENT.
135
137
  see: https://googleapis.dev/python/storage/latest/client.html#google.cloud.storage.client.Client.bucket
136
138
  """
137
139
  storage_client = _get_storage_client()
@@ -160,26 +162,26 @@ def _get_bigquery_dataset(dataset_id: str) -> bigquery.Dataset:
160
162
  Get the bigquery dataset with the id 'dataset_id'.
161
163
  makes an API request to pull this with the bigquery client
162
164
  """
163
- global _bigquery_client
164
- if _bigquery_client is None:
165
+ global BIGQUERY_CLIENT
166
+ if BIGQUERY_CLIENT is None:
165
167
  credentials = Credentials.from_service_account_info(
166
- json.loads(secret_manager.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
168
+ json.loads(SECRET_MANAGER.get(environ.get("APP_ENGINE_CREDENTIALS_ID")))
167
169
  )
168
170
  # client_options = ClientOptions(api_endpoint=os.environ.get("DEV_GOOGLE_BIGQUERY"))
169
- # _bigquery_client = bigquery.Client(client_options=client_options, credentials=credentials)
170
- _bigquery_client = bigquery.Client(credentials=credentials)
171
+ # BIGQUERY_CLIENT = bigquery.Client(client_options=client_options, credentials=credentials)
172
+ BIGQUERY_CLIENT = bigquery.Client(credentials=credentials)
171
173
 
172
- dataset = _bigquery_client.get_dataset(dataset_id) # Make an API request.
174
+ dataset = BIGQUERY_CLIENT.get_dataset(dataset_id) # Make an API request.
173
175
 
174
176
  return dataset
175
177
 
176
178
 
177
- _xlsx_gcs_uri_format = (
179
+ XLSX_GCS_URI_FORMAT = (
178
180
  "{trial_id}/xlsx/{template_category}/{template_type}/{upload_moment}.xlsx"
179
181
  )
180
182
 
181
183
 
182
- _pseudo_blob = namedtuple(
184
+ PseudoBblob = namedtuple(
183
185
  "_pseudo_blob", ["name", "size", "md5_hash", "crc32c", "time_created"]
184
186
  )
185
187
 
@@ -200,7 +202,7 @@ def upload_xlsx_to_gcs(
200
202
  Returns:
201
203
  arg1: GCS blob object
202
204
  """
203
- blob_name = _xlsx_gcs_uri_format.format(
205
+ blob_name = XLSX_GCS_URI_FORMAT.format(
204
206
  trial_id=trial_id,
205
207
  template_category=template_category,
206
208
  template_type=template_type,
@@ -211,7 +213,7 @@ def upload_xlsx_to_gcs(
211
213
  logger.info(
212
214
  f"Would've saved {blob_name} to {GOOGLE_UPLOAD_BUCKET} and {GOOGLE_ACL_DATA_BUCKET}"
213
215
  )
214
- return _pseudo_blob(
216
+ return PseudoBblob(
215
217
  blob_name, 0, "_pseudo_md5_hash", "_pseudo_crc32c", upload_moment
216
218
  )
217
219
 
@@ -410,7 +412,7 @@ def get_blob_names(
410
412
  blob_list.extend(
411
413
  storage_client.list_blobs(GOOGLE_ACL_DATA_BUCKET, prefix=prefix)
412
414
  )
413
- return set([blob.name for blob in blob_list])
415
+ return {blob.name for blob in blob_list}
414
416
 
415
417
 
416
418
  def grant_download_access_to_blob_names(
@@ -552,14 +554,11 @@ def _build_trial_upload_prefixes(
552
554
  if not trial_id:
553
555
  from ..models.models import TrialMetadata
554
556
 
555
- trial_set = set(
556
- [
557
- str(t.trial_id)
558
- for t in session.query(TrialMetadata).add_columns(
559
- TrialMetadata.trial_id
560
- )
561
- ]
562
- )
557
+ trial_set = {
558
+ str(t.trial_id)
559
+ for t in session.query(TrialMetadata).add_columns(TrialMetadata.trial_id)
560
+ }
561
+
563
562
  else:
564
563
  trial_set = set([trial_id])
565
564
 
@@ -654,7 +653,7 @@ def grant_bigquery_iam_access(policy: Policy, user_emails: List[str]) -> None:
654
653
 
655
654
  # try to set the new policy with edits
656
655
  try:
657
- _crm_service.projects().setIamPolicy(
656
+ CRM_SERVICE.projects().setIamPolicy(
658
657
  resource=GOOGLE_CLOUD_PROJECT,
659
658
  body={
660
659
  "policy": policy,
@@ -677,7 +676,7 @@ def grant_bigquery_iam_access(policy: Policy, user_emails: List[str]) -> None:
677
676
  )
678
677
  )
679
678
  dataset.access_entries = entries
680
- _bigquery_client.update_dataset(dataset, ["access_entries"]) # Make an API request.
679
+ BIGQUERY_CLIENT.update_dataset(dataset, ["access_entries"]) # Make an API request.
681
680
 
682
681
 
683
682
  # Arbitrary upper bound on the number of GCS IAM bindings we expect a user to have for uploads
@@ -731,7 +730,7 @@ def revoke_bigquery_iam_access(policy: Policy, user_email: str) -> None:
731
730
  # try update of the policy
732
731
  try:
733
732
  policy = (
734
- _crm_service.projects()
733
+ CRM_SERVICE.projects()
735
734
  .setIamPolicy(
736
735
  resource=GOOGLE_CLOUD_PROJECT,
737
736
  body={
@@ -753,14 +752,15 @@ def revoke_bigquery_iam_access(policy: Policy, user_email: str) -> None:
753
752
  entry for entry in entries if entry.entity_id != user_email
754
753
  ]
755
754
 
756
- dataset = _bigquery_client.update_dataset(
755
+ dataset = BIGQUERY_CLIENT.update_dataset(
757
756
  dataset,
758
757
  # Update just the `access_entries` property of the dataset.
759
758
  ["access_entries"],
760
759
  ) # Make an API request.
761
760
 
762
761
 
763
- user_member = lambda email: f"user:{email}"
762
+ def user_member(email):
763
+ return f"user:{email}"
764
764
 
765
765
 
766
766
  def _build_storage_iam_binding(
@@ -897,26 +897,28 @@ def _encode_and_publish(content: str, topic: str) -> Future:
897
897
  logger.info(
898
898
  f"Publishing message {content!r} to topic {DEV_CFUNCTIONS_SERVER}/{topic}"
899
899
  )
900
- import base64
901
900
 
902
901
  bdata = base64.b64encode(content.encode("utf-8"))
903
902
  try:
904
903
  res = requests.post(
905
- f"{DEV_CFUNCTIONS_SERVER}/{topic}", data={"data": bdata}
904
+ f"{DEV_CFUNCTIONS_SERVER}/{topic}",
905
+ data={"data": bdata},
906
+ timeout=TIMEOUT_IN_SECONDS,
906
907
  )
907
908
  except Exception as e:
908
909
  raise Exception(
909
910
  f"Couldn't publish message {content!r} to topic {DEV_CFUNCTIONS_SERVER}/{topic}"
910
911
  ) from e
911
- else:
912
- logger.info(f"Got {res}")
913
- if res.status_code != 200:
914
- raise Exception(
915
- f"Couldn't publish message {content!r} to {DEV_CFUNCTIONS_SERVER}/{topic}: {res!r}"
916
- )
912
+
913
+ logger.info(f"Got {res}")
914
+ if res.status_code != 200:
915
+ raise Exception(
916
+ f"Couldn't publish message {content!r} to {DEV_CFUNCTIONS_SERVER}/{topic}: {res!r}"
917
+ )
918
+
917
919
  else:
918
920
  logger.info(f"Would've published message {content} to topic {topic}")
919
- return
921
+ return None
920
922
 
921
923
  # The Pub/Sub publisher client returns a concurrent.futures.Future
922
924
  # containing info about whether the publishing was successful.
@@ -965,7 +967,7 @@ def send_email(to_emails: List[str], subject: str, html_content: str, **kw) -> N
965
967
 
966
968
  logger.info(f"({ENV}) Sending email to {to_emails} with subject {subject}")
967
969
  email_json = json.dumps(
968
- dict(to_emails=to_emails, subject=subject, html_content=html_content, **kw)
970
+ {"to_emails": to_emails, "subject": subject, "html_content": html_content, **kw}
969
971
  )
970
972
 
971
973
  report = _encode_and_publish(email_json, GOOGLE_EMAILS_TOPIC)
@@ -1,4 +1,5 @@
1
1
  """Shared utility functions for building CIDC API resource endpoints."""
2
+
2
3
  from functools import wraps
3
4
  from typing import Optional, Callable, Union
4
5
 
@@ -6,6 +7,7 @@ from flask import request, jsonify
6
7
  from webargs import fields
7
8
  from webargs.flaskparser import use_args
8
9
  from marshmallow import validate
10
+ from marshmallow.exceptions import ValidationError
9
11
  from werkzeug.exceptions import (
10
12
  PreconditionRequired,
11
13
  PreconditionFailed,
@@ -13,7 +15,6 @@ from werkzeug.exceptions import (
13
15
  BadRequest,
14
16
  UnprocessableEntity,
15
17
  )
16
- from marshmallow.exceptions import ValidationError
17
18
 
18
19
  from ..models import BaseModel, BaseSchema, ValidationMultiError
19
20
 
@@ -48,11 +49,11 @@ def unmarshal_request(schema: BaseSchema, kwarg_name: str, load_sqla: bool = Tru
48
49
  loaded_instance.validate()
49
50
  # The many ways that validation errors might get raised...
50
51
  except ValueError as e:
51
- raise UnprocessableEntity(str(e))
52
+ raise UnprocessableEntity(str(e)) from e
52
53
  except ValidationError as e:
53
- raise UnprocessableEntity(e.messages)
54
+ raise UnprocessableEntity(e.messages) from e
54
55
  except ValidationMultiError as e:
55
- raise UnprocessableEntity({"errors": e.args[0]})
56
+ raise UnprocessableEntity({"errors": e.args[0]}) from e
56
57
 
57
58
  kwargs[kwarg_name] = body
58
59
 
@@ -186,7 +187,7 @@ def use_args_with_pagination(argmap: dict, model_schema: BaseSchema):
186
187
  return {k: v for k, v in args.items() if k in argmap.keys()}
187
188
 
188
189
  def get_pagination_args(args: dict):
189
- return {k: v for k, v in args.items() if k in pagination_argmap.keys()}
190
+ return {k: v for k, v in args.items() if k in pagination_argmap}
190
191
 
191
192
  def decorator(endpoint):
192
193
  @wraps(endpoint)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nci_cidc_api_modules
3
- Version: 1.0.0
3
+ Version: 1.0.1
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
@@ -0,0 +1,25 @@
1
+ cidc_api/config/__init__.py,sha256=5kcMGor07TrBm6e_UW6CCVnJu5wJ-8QX8X9ZRmeuPKA,147
2
+ cidc_api/config/db.py,sha256=ayeeNV-sV20hGoFyMMTMncI2V-FI9lVN3JV-Lmpr3xI,1981
3
+ cidc_api/config/logging.py,sha256=gJ2TGgQVREng4Hv0phlCCkQai7HhumKYjJxubpxS6Q0,1090
4
+ cidc_api/config/secrets.py,sha256=2DXeew1Pm0lnf2SLuo8wW5c5kOJp2WrhjflxZGsY_Ng,1505
5
+ cidc_api/config/settings.py,sha256=Ua6UpiQu9l1ZD-YlmpaWuQOv9tPyYLxWFLC2DEJdAyQ,4044
6
+ cidc_api/csms/__init__.py,sha256=eJkY6rWNOAUBmSd4G1_U6h7i472druKEtBdVmgFZVPg,20
7
+ cidc_api/csms/auth.py,sha256=25Yma2Kz3KLENAPSeBYacFuSZXng-EDgmgInKBsRyP0,3191
8
+ cidc_api/models/__init__.py,sha256=bl445G8Zic9YbhZ8ZBni07wtBMhLJRMBA-JqjLxx2bw,66
9
+ cidc_api/models/csms_api.py,sha256=Wp4b53vwOqSlOIaoAYGlI1p8ZfXRXmVJ6MLcsvzq0LA,31664
10
+ cidc_api/models/migrations.py,sha256=gp9vtkYbA9FFy2s-7woelAmsvQbJ41LO2_DY-YkFIrQ,11464
11
+ cidc_api/models/models.py,sha256=AYt0rIzaeQ0HHlTSeerbTpYwMJwqt93aadOuFLLEqBA,120820
12
+ cidc_api/models/schemas.py,sha256=7tDYtmULuzTt2kg7RorWhte06ffalgpQKrFiDRGcPEQ,2711
13
+ cidc_api/models/files/__init__.py,sha256=8BMTnUSHzUbz0lBeEQY6NvApxDD3GMWMduoVMos2g4Y,213
14
+ cidc_api/models/files/details.py,sha256=eg1u8uZwtxb0m9mFobcTL_mnPBMq1MPZv3NN3KWMGOI,62309
15
+ cidc_api/models/files/facets.py,sha256=5xI5eM1J0Uc97W0-MvAPSRRN-2Hs2xb_AIupliJRMJU,29172
16
+ cidc_api/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ cidc_api/shared/auth.py,sha256=VMd_3QJE2iG16QxuGzHBV9MzJJItOZNn9gcw0_iUBLI,11647
18
+ cidc_api/shared/emails.py,sha256=AhSp2hxWyuMpe21pERuQwrAEy0yCfy3rvSygDNKtgdc,4820
19
+ cidc_api/shared/gcloud_client.py,sha256=7dDs0crLMJKdIp4IDSfrZBMB3h-zvWNieB81azoeLO4,33746
20
+ cidc_api/shared/rest_utils.py,sha256=LMfBpvJRjkfQjCzVXuhTTe4Foz4wlvaKg6QntyR-Hkc,6648
21
+ nci_cidc_api_modules-1.0.1.dist-info/LICENSE,sha256=pNYWVTHaYonnmJyplmeAp7tQAjosmDpAWjb34jjv7Xs,1102
22
+ nci_cidc_api_modules-1.0.1.dist-info/METADATA,sha256=rhlYaotiiwG6djDCZaSq5GT9CcE_2YVlHs_gnSd9tgY,40275
23
+ nci_cidc_api_modules-1.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
24
+ nci_cidc_api_modules-1.0.1.dist-info/top_level.txt,sha256=rNiRzL0lJGi5Q9tY9uSoMdTbJ-7u5c_D2E86KA94yRA,9
25
+ nci_cidc_api_modules-1.0.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,25 +0,0 @@
1
- cidc_api/config/__init__.py,sha256=5kcMGor07TrBm6e_UW6CCVnJu5wJ-8QX8X9ZRmeuPKA,147
2
- cidc_api/config/db.py,sha256=cw0wTfcak_FyAKZE8oKVYLVkph644Lv-_MAbYutGV44,1978
3
- cidc_api/config/logging.py,sha256=gJ2TGgQVREng4Hv0phlCCkQai7HhumKYjJxubpxS6Q0,1090
4
- cidc_api/config/secrets.py,sha256=DlloiKiy420WJO250SfKs_-T0wKYPbgdwyPncP5MGLY,1518
5
- cidc_api/config/settings.py,sha256=GyeGDCj1tt61u4fbhomPIDq_fiamRMIT6dQPY1ufl-w,4076
6
- cidc_api/csms/__init__.py,sha256=eJkY6rWNOAUBmSd4G1_U6h7i472druKEtBdVmgFZVPg,20
7
- cidc_api/csms/auth.py,sha256=upJ52PX-u1KD4I0-Hy4JptCp_cp6qgs_ZMXPxqfeVI0,3071
8
- cidc_api/models/__init__.py,sha256=bl445G8Zic9YbhZ8ZBni07wtBMhLJRMBA-JqjLxx2bw,66
9
- cidc_api/models/csms_api.py,sha256=ubT-1Z5ajh5slAZ1jUvY8_0xKKl-7AVMwpQy0QT08eU,31379
10
- cidc_api/models/migrations.py,sha256=Z2ycc-0XWdOnfDmCPFNXdg0lHLL8sDLIlhJHiEeYrv8,11292
11
- cidc_api/models/models.py,sha256=7VQHkvDDCFoAiZR7Rz6J5roaLoG16LtlgFlkC5ocDGc,119987
12
- cidc_api/models/schemas.py,sha256=7tDYtmULuzTt2kg7RorWhte06ffalgpQKrFiDRGcPEQ,2711
13
- cidc_api/models/files/__init__.py,sha256=8BMTnUSHzUbz0lBeEQY6NvApxDD3GMWMduoVMos2g4Y,213
14
- cidc_api/models/files/details.py,sha256=YP0vvc3QsDzcZlBbYeNjzkprVaDrYHHnspdsSAm_a2g,63531
15
- cidc_api/models/files/facets.py,sha256=pigQhlQwuFyJ6Im8QByfaeeX36px2kKA77coQsJ8wM8,29169
16
- cidc_api/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- cidc_api/shared/auth.py,sha256=KOmakviByttH4b3yFw0zmcjciA-245AWabz8qatIcRQ,11475
18
- cidc_api/shared/emails.py,sha256=AhSp2hxWyuMpe21pERuQwrAEy0yCfy3rvSygDNKtgdc,4820
19
- cidc_api/shared/gcloud_client.py,sha256=jd1R7PNhuo1ULBFhqI6E1wRGLC7DzfPxLzbZ5yE38cU,33839
20
- cidc_api/shared/rest_utils.py,sha256=MCUypPmOOHKQR-vThkSMj8Fe8m_lZmv85jViCxZgGPE,6633
21
- nci_cidc_api_modules-1.0.0.dist-info/LICENSE,sha256=pNYWVTHaYonnmJyplmeAp7tQAjosmDpAWjb34jjv7Xs,1102
22
- nci_cidc_api_modules-1.0.0.dist-info/METADATA,sha256=c5Vszw16CSoCI4NvE1pTXXV6k-bRJEHwr-NSAF3OCCY,40275
23
- nci_cidc_api_modules-1.0.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
24
- nci_cidc_api_modules-1.0.0.dist-info/top_level.txt,sha256=rNiRzL0lJGi5Q9tY9uSoMdTbJ-7u5c_D2E86KA94yRA,9
25
- nci_cidc_api_modules-1.0.0.dist-info/RECORD,,