From ebe41c9874ccf0326b925462afd6f8f672b6671e Mon Sep 17 00:00:00 2001 From: Donny Winston Date: Mon, 6 Nov 2023 15:15:31 -0500 Subject: [PATCH] fix: use @field_serializer for pydantic `Url`s (#363) * fix: use @field_serializer for pydantic `Url`s ensures `model_dump` preserves python `datetime`s, which are handled by pymongo. reverts mode='json' option to model_dump, to preserve datetimes. fixes #349 * fix: preserve exclude_unset * style: remove `print` for debugging * fix: remove stale comment --- .../workflow_execution_activity/core.py | 4 +- nmdc_runtime/api/endpoints/objects.py | 6 +-- nmdc_runtime/api/endpoints/operations.py | 4 +- nmdc_runtime/api/endpoints/queries.py | 10 ++--- nmdc_runtime/api/endpoints/runs.py | 6 +-- nmdc_runtime/api/endpoints/search.py | 4 +- nmdc_runtime/api/endpoints/sites.py | 12 +----- nmdc_runtime/api/endpoints/users.py | 22 +++-------- nmdc_runtime/api/endpoints/util.py | 18 +++------ nmdc_runtime/api/main.py | 10 ++--- nmdc_runtime/api/models/object.py | 23 +++++++++++ nmdc_runtime/api/models/operation.py | 6 ++- nmdc_runtime/api/models/run.py | 18 ++------- nmdc_runtime/minter/adapters/repository.py | 13 +------ .../minter/entrypoints/fastapi_app.py | 4 +- nmdc_runtime/site/drsobjects/ingest.py | 6 +-- nmdc_runtime/site/ops.py | 15 ++------ nmdc_runtime/site/repository.py | 4 +- nmdc_runtime/site/resources.py | 4 +- tests/integration/test_minter_repository.py | 38 +++---------------- tests/test_api/test_endpoints.py | 12 +++--- tests/test_graphs/ensure_jobs.py | 26 +++++++++++++ 22 files changed, 106 insertions(+), 159 deletions(-) create mode 100644 tests/test_graphs/ensure_jobs.py diff --git a/components/nmdc_runtime/workflow_execution_activity/core.py b/components/nmdc_runtime/workflow_execution_activity/core.py index ad7d020d..43236234 100644 --- a/components/nmdc_runtime/workflow_execution_activity/core.py +++ b/components/nmdc_runtime/workflow_execution_activity/core.py @@ -94,9 +94,7 @@ def insert_into_keys( workflow: Workflow, data_objects: list[DataObject] ) -> dict[str, Any]: """Insert data object url into correct workflow input field.""" - workflow_dict = workflow.model_dump( - mode="json", - ) + workflow_dict = workflow.model_dump() for key in workflow_dict["inputs"]: for do in data_objects: if workflow_dict["inputs"][key] == str(do.data_object_type): diff --git a/nmdc_runtime/api/endpoints/objects.py b/nmdc_runtime/api/endpoints/objects.py index 0dd3b443..706f9049 100644 --- a/nmdc_runtime/api/endpoints/objects.py +++ b/nmdc_runtime/api/endpoints/objects.py @@ -78,7 +78,7 @@ def create_object( """ id_supplied = supplied_object_id( - mdb, client_site, object_in.model_dump(mode="json", exclude_unset=True) + mdb, client_site, object_in.model_dump(exclude_unset=True) ) drs_id = local_part( id_supplied if id_supplied is not None else generate_one_id(mdb, S3_ID_NS) @@ -255,9 +255,7 @@ def update_object( status_code=status.HTTP_403_FORBIDDEN, detail=f"client authorized for different site_id than {object_mgr_site}", ) - doc_object_patched = merge( - doc, object_patch.model_dump(mode="json", exclude_unset=True) - ) + doc_object_patched = merge(doc, object_patch.model_dump(exclude_unset=True)) mdb.operations.replace_one({"id": object_id}, doc_object_patched) return doc_object_patched diff --git a/nmdc_runtime/api/endpoints/operations.py b/nmdc_runtime/api/endpoints/operations.py index ecb4d33e..c6bcccf2 100644 --- a/nmdc_runtime/api/endpoints/operations.py +++ b/nmdc_runtime/api/endpoints/operations.py @@ -61,13 +61,13 @@ def update_operation( detail=f"client authorized for different site_id than {site_id_op}", ) op_patch_metadata = merge( - op_patch.model_dump(mode="json", exclude_unset=True).get("metadata", {}), + op_patch.model_dump(exclude_unset=True).get("metadata", {}), pick(["site_id", "job", "model"], doc_op.get("metadata", {})), ) doc_op_patched = merge( doc_op, assoc( - op_patch.model_dump(mode="json", exclude_unset=True), + op_patch.model_dump(exclude_unset=True), "metadata", op_patch_metadata, ), diff --git a/nmdc_runtime/api/endpoints/queries.py b/nmdc_runtime/api/endpoints/queries.py index 11417698..3d57166a 100644 --- a/nmdc_runtime/api/endpoints/queries.py +++ b/nmdc_runtime/api/endpoints/queries.py @@ -75,9 +75,9 @@ def run_query( id=qid, saved_at=saved_at, ) - mdb.queries.insert_one(query.model_dump(mode="json", exclude_unset=True)) + mdb.queries.insert_one(query.model_dump(exclude_unset=True)) cmd_response = _run_query(query, mdb) - return unmongo(cmd_response.model_dump(mode="json", exclude_unset=True)) + return unmongo(cmd_response.model_dump(exclude_unset=True)) @router.get("/queries/{query_id}", response_model=Query) @@ -107,7 +107,7 @@ def rerun_query( check_can_delete(user) cmd_response = _run_query(query, mdb) - return unmongo(cmd_response.model_dump(mode="json", exclude_unset=True)) + return unmongo(cmd_response.model_dump(exclude_unset=True)) def _run_query(query, mdb) -> CommandResponse: @@ -131,12 +131,12 @@ def _run_query(query, mdb) -> CommandResponse: detail="Failed to back up to-be-deleted documents. operation aborted.", ) - q_response = mdb.command(query.cmd.model_dump(mode="json", exclude_unset=True)) + q_response = mdb.command(query.cmd.model_dump(exclude_unset=True)) cmd_response: CommandResponse = command_response_for(q_type)(**q_response) query_run = ( QueryRun(qid=query.id, ran_at=ran_at, result=cmd_response) if cmd_response.ok else QueryRun(qid=query.id, ran_at=ran_at, error=cmd_response) ) - mdb.query_runs.insert_one(query_run.model_dump(mode="json", exclude_unset=True)) + mdb.query_runs.insert_one(query_run.model_dump(exclude_unset=True)) return cmd_response diff --git a/nmdc_runtime/api/endpoints/runs.py b/nmdc_runtime/api/endpoints/runs.py index 8bd9f22d..7c41ad84 100644 --- a/nmdc_runtime/api/endpoints/runs.py +++ b/nmdc_runtime/api/endpoints/runs.py @@ -94,9 +94,5 @@ def post_run_event( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Supplied run_event.run.id does not match run_id given in request URL.", ) - mdb.run_events.insert_one( - run_event.model_dump( - mode="json", - ) - ) + mdb.run_events.insert_one(run_event.model_dump()) return _get_run_summary(run_event.run.id, mdb) diff --git a/nmdc_runtime/api/endpoints/search.py b/nmdc_runtime/api/endpoints/search.py index 4813f7d2..b48c411e 100644 --- a/nmdc_runtime/api/endpoints/search.py +++ b/nmdc_runtime/api/endpoints/search.py @@ -25,9 +25,7 @@ def data_objects( req: DataObjectListRequest = Depends(), mdb: MongoDatabase = Depends(get_mongo_db), ): - filter_ = list_request_filter_to_mongo_filter( - req.model_dump(mode="json", exclude_unset=True) - ) + filter_ = list_request_filter_to_mongo_filter(req.model_dump(exclude_unset=True)) max_page_size = filter_.pop("max_page_size", None) page_token = filter_.pop("page_token", None) req = ListRequest( diff --git a/nmdc_runtime/api/endpoints/sites.py b/nmdc_runtime/api/endpoints/sites.py index 76adfdc1..9e587d03 100644 --- a/nmdc_runtime/api/endpoints/sites.py +++ b/nmdc_runtime/api/endpoints/sites.py @@ -56,11 +56,7 @@ def create_site( status_code=status.HTTP_409_CONFLICT, detail=f"site with supplied id {site.id} already exists", ) - mdb.sites.insert_one( - site.model_dump( - mode="json", - ) - ) + mdb.sites.insert_one(site.model_dump()) refresh_minter_requesters_from_sites() rv = mdb.users.update_one( {"username": user.username}, @@ -169,11 +165,7 @@ def put_object_in_site( }, } ) - mdb.operations.insert_one( - op.model_dump( - mode="json", - ) - ) + mdb.operations.insert_one(op.model_dump()) return op diff --git a/nmdc_runtime/api/endpoints/users.py b/nmdc_runtime/api/endpoints/users.py index 587ad453..5799ca3c 100644 --- a/nmdc_runtime/api/endpoints/users.py +++ b/nmdc_runtime/api/endpoints/users.py @@ -35,11 +35,7 @@ async def login_for_access_token( detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) - access_token_expires = timedelta( - **ACCESS_TOKEN_EXPIRES.model_dump( - mode="json", - ) - ) + access_token_expires = timedelta(**ACCESS_TOKEN_EXPIRES.model_dump()) access_token = create_access_token( data={"sub": f"user:{user.username}"}, expires_delta=access_token_expires ) @@ -54,11 +50,7 @@ async def login_for_access_token( headers={"WWW-Authenticate": "Bearer"}, ) # TODO make below an absolute time - access_token_expires = timedelta( - **ACCESS_TOKEN_EXPIRES.model_dump( - mode="json", - ) - ) + access_token_expires = timedelta(**ACCESS_TOKEN_EXPIRES.model_dump()) access_token = create_access_token( data={"sub": f"client:{form_data.client_id}"}, expires_delta=access_token_expires, @@ -66,9 +58,7 @@ async def login_for_access_token( return { "access_token": access_token, "token_type": "bearer", - "expires": ACCESS_TOKEN_EXPIRES.model_dump( - mode="json", - ), + "expires": ACCESS_TOKEN_EXPIRES.model_dump(), } @@ -94,10 +84,8 @@ def create_user( check_can_create_user(requester) mdb.users.insert_one( UserInDB( - **user_in.model_dump( - mode="json", - ), + **user_in.model_dump(), hashed_password=get_password_hash(user_in.password), - ).model_dump(mode="json", exclude_unset=True) + ).model_dump(exclude_unset=True) ) return mdb.users.find_one({"username": user_in.username}) diff --git a/nmdc_runtime/api/endpoints/util.py b/nmdc_runtime/api/endpoints/util.py index 9b228bda..fd473682 100644 --- a/nmdc_runtime/api/endpoints/util.py +++ b/nmdc_runtime/api/endpoints/util.py @@ -454,11 +454,11 @@ def _create_object( mdb: MongoDatabase, object_in: DrsObjectIn, mgr_site, drs_id, self_uri ): drs_obj = DrsObject( - **object_in.model_dump(exclude_unset=True, mode="json"), + **object_in.model_dump(exclude_unset=True), id=drs_id, self_uri=self_uri, ) - doc = drs_obj.model_dump(exclude_unset=True, mode="json") + doc = drs_obj.model_dump(exclude_unset=True) doc["_mgr_site"] = mgr_site # manager site try: mdb.objects.insert_one(doc) @@ -519,22 +519,16 @@ def _claim_job(job_id: str, mdb: MongoDatabase, site: Site): "workflow": job.workflow, "config": job.config, } - ).model_dump(mode="json", exclude_unset=True), + ).model_dump(exclude_unset=True), "site_id": site.id, "model": dotted_path_for(JobOperationMetadata), }, } ) - mdb.operations.insert_one( - op.model_dump( - mode="json", - ) - ) - mdb.jobs.replace_one( - {"id": job.id}, job.model_dump(mode="json", exclude_unset=True) - ) + mdb.operations.insert_one(op.model_dump()) + mdb.jobs.replace_one({"id": job.id}, job.model_dump(exclude_unset=True)) - return op.model_dump(mode="json", exclude_unset=True) + return op.model_dump(exclude_unset=True) @lru_cache diff --git a/nmdc_runtime/api/main.py b/nmdc_runtime/api/main.py index 2a348aa1..71a6863e 100644 --- a/nmdc_runtime/api/main.py +++ b/nmdc_runtime/api/main.py @@ -234,9 +234,7 @@ def ensure_initial_resources_on_boot(): collection_boot = import_module(f"nmdc_runtime.api.boot.{collection_name}") for model in collection_boot.construct(): - doc = model.model_dump( - mode="json", - ) + doc = model.model_dump() mdb[collection_name].replace_one({"id": doc["id"]}, doc, upsert=True) username = os.getenv("API_ADMIN_USER") @@ -248,7 +246,7 @@ def ensure_initial_resources_on_boot(): username=username, hashed_password=get_password_hash(os.getenv("API_ADMIN_PASS")), site_admin=[os.getenv("API_SITE_ID")], - ).model_dump(mode="json", exclude_unset=True), + ).model_dump(exclude_unset=True), upsert=True, ) mdb.users.create_index("username") @@ -269,9 +267,7 @@ def ensure_initial_resources_on_boot(): ), ) ], - ).model_dump( - mode="json", - ), + ).model_dump(), upsert=True, ) diff --git a/nmdc_runtime/api/models/object.py b/nmdc_runtime/api/models/object.py index 26af100c..17df772c 100644 --- a/nmdc_runtime/api/models/object.py +++ b/nmdc_runtime/api/models/object.py @@ -12,6 +12,7 @@ BaseModel, AnyUrl, HttpUrl, + field_serializer, ) from typing_extensions import Annotated @@ -31,6 +32,10 @@ class AccessURL(BaseModel): headers: Optional[Dict[str, str]] = None url: AnyUrl + @field_serializer("url") + def serialize_url(self, url: AnyUrl, _info): + return str(url) + class AccessMethod(BaseModel): access_id: Optional[Annotated[str, StringConstraints(min_length=1)]] = None @@ -78,6 +83,12 @@ def no_contents_means_single_blob(cls, values): raise ValueError("no contents means no further nesting, so id required") return values + @field_serializer("drs_uri") + def serialize_url(self, drs_uri: Optional[List[AnyUrl]], _info): + if drs_uri is not None and len(drs_uri) > 0: + return [str(u) for u in drs_uri] + return drs_uri + ContentsObject.update_forward_refs() @@ -127,6 +138,10 @@ class DrsObject(DrsObjectIn): id: DrsId self_uri: AnyUrl + @field_serializer("self_uri") + def serialize_url(self, self_uri: AnyUrl, _info): + return str(self_uri) + Seconds = Annotated[int, Field(strict=True, gt=0)] @@ -135,6 +150,10 @@ class ObjectPresignedUrl(BaseModel): url: HttpUrl expires_in: Seconds = 300 + @field_serializer("url") + def serialize_url(self, url: HttpUrl, _info): + return str(url) + class DrsObjectOutBase(DrsObjectBase): checksums: List[Checksum] @@ -145,6 +164,10 @@ class DrsObjectOutBase(DrsObjectBase): updated_time: Optional[datetime.datetime] = None version: Optional[str] = None + @field_serializer("self_uri") + def serialize_url(self, slf_uri: AnyUrl, _info): + return str(self_uri) + class DrsObjectBlobOut(DrsObjectOutBase): access_methods: List[AccessMethod] diff --git a/nmdc_runtime/api/models/operation.py b/nmdc_runtime/api/models/operation.py index e1819f24..035100cd 100644 --- a/nmdc_runtime/api/models/operation.py +++ b/nmdc_runtime/api/models/operation.py @@ -1,7 +1,7 @@ import datetime from typing import Generic, TypeVar, Optional, List, Any, Union -from pydantic import StringConstraints, BaseModel, HttpUrl +from pydantic import StringConstraints, BaseModel, HttpUrl, field_serializer from nmdc_runtime.api.models.util import ResultT from typing_extensions import Annotated @@ -59,3 +59,7 @@ class ObjectPutMetadata(Metadata): site_id: str url: HttpUrl expires_in_seconds: int + + @field_serializer("url") + def serialize_url(self, url: HttpUrl, _info): + return str(url) diff --git a/nmdc_runtime/api/models/run.py b/nmdc_runtime/api/models/run.py index 43bf734e..3cdf43d1 100644 --- a/nmdc_runtime/api/models/run.py +++ b/nmdc_runtime/api/models/run.py @@ -93,11 +93,7 @@ def _add_run_requested_event(run_spec: RunUserSpec, mdb: MongoDatabase, user: Us time=now(as_str=True), inputs=run_spec.inputs, ) - mdb.run_events.insert_one( - event.model_dump( - mode="json", - ) - ) + mdb.run_events.insert_one(event.model_dump()) return run_id @@ -117,9 +113,7 @@ def _add_run_started_event(run_id: str, mdb: MongoDatabase): job=requested.job, type=RunEventType.STARTED, time=now(as_str=True), - ).model_dump( - mode="json", - ) + ).model_dump() ) return run_id @@ -140,9 +134,7 @@ def _add_run_fail_event(run_id: str, mdb: MongoDatabase): job=requested.job, type=RunEventType.FAIL, time=now(as_str=True), - ).model_dump( - mode="json", - ) + ).model_dump() ) return run_id @@ -164,8 +156,6 @@ def _add_run_complete_event(run_id: str, mdb: MongoDatabase, outputs: List[str]) type=RunEventType.COMPLETE, time=now(as_str=True), outputs=outputs, - ).model_dump( - mode="json", - ) + ).model_dump() ) return run_id diff --git a/nmdc_runtime/minter/adapters/repository.py b/nmdc_runtime/minter/adapters/repository.py index 879bdcc8..96775c92 100644 --- a/nmdc_runtime/minter/adapters/repository.py +++ b/nmdc_runtime/minter/adapters/repository.py @@ -97,9 +97,7 @@ def mint(self, req_mint: MintingRequest) -> list[Identifier]: ) ) for id_ in ids: - self.db[id_.id] = id_.model_dump( - mode="json", - ) + self.db[id_.id] = id_.model_dump() return ids def bind(self, req_bind: BindingRequest) -> Identifier: @@ -186,14 +184,7 @@ def mint(self, req_mint: MintingRequest) -> list[Identifier]: ) for id_name in not_taken ] - self.db["minter.id_records"].insert_many( - [ - i.model_dump( - mode="json", - ) - for i in ids - ] - ) + self.db["minter.id_records"].insert_many([i.model_dump() for i in ids]) collected.extend(ids) if len(collected) == req_mint.how_many: break diff --git a/nmdc_runtime/minter/entrypoints/fastapi_app.py b/nmdc_runtime/minter/entrypoints/fastapi_app.py index 3d4b7efc..996cb575 100644 --- a/nmdc_runtime/minter/entrypoints/fastapi_app.py +++ b/nmdc_runtime/minter/entrypoints/fastapi_app.py @@ -40,9 +40,7 @@ def mint_ids( MintingRequest( service=service, requester=requester, - **req_mint.model_dump( - mode="json", - ), + **req_mint.model_dump(), ) ) return [d.id for d in minted] diff --git a/nmdc_runtime/site/drsobjects/ingest.py b/nmdc_runtime/site/drsobjects/ingest.py index 26a26f43..42eeb8a5 100644 --- a/nmdc_runtime/site/drsobjects/ingest.py +++ b/nmdc_runtime/site/drsobjects/ingest.py @@ -44,11 +44,7 @@ def claim_metadata_ingest_jobs( ) jobs = [] while True: - rv = client.list_jobs( - lr.model_dump( - mode="json", - ) - ).json() + rv = client.list_jobs(lr.model_dump()).json() jobs.extend(rv["resources"]) if "next_page_token" not in rv: break diff --git a/nmdc_runtime/site/ops.py b/nmdc_runtime/site/ops.py index 265498ab..eecd4665 100644 --- a/nmdc_runtime/site/ops.py +++ b/nmdc_runtime/site/ops.py @@ -267,11 +267,7 @@ def get_operation(context): def produce_curated_db(context, op: Operation): client: RuntimeApiSiteClient = context.resources.runtime_api_site_client mdb: MongoDatabase = context.resources.mongo.db - op = Operation[ResultT, JobOperationMetadata]( - **op.model_dump( - mode="json", - ) - ) + op = Operation[ResultT, JobOperationMetadata](**op.model_dump()) op_meta: JobOperationMetadata = op.metadata job_id = op_meta.job.id job = mdb.jobs.find_one({"id": job_id}) @@ -354,12 +350,7 @@ def filter_ops_undone_expired() -> str: @op(required_resource_keys={"runtime_api_site_client"}) def list_operations(context, filter_: str) -> list: client = context.resources.runtime_api_site_client - ops = [ - op.model_dump( - mode="json", - ) - for op in client.list_operations({"filter": filter_}) - ] + ops = [op.model_dump() for op in client.list_operations({"filter": filter_})] context.log.info(str(len(ops))) return ops @@ -475,7 +466,7 @@ def perform_changesheet_updates(context, sheet_in: ChangesheetIn): op = Operation(**mdb.operations.find_one({"id": op_id})) op.done = True op.result = {"update_cmd": json.dumps(update_cmd)} - op_doc = op.model_dump(mode="json", exclude_unset=True) + op_doc = op.model_dump(exclude_unset=True) mdb.operations.replace_one({"id": op_id}, op_doc) return ["/operations/" + op_doc["id"]] diff --git a/nmdc_runtime/site/repository.py b/nmdc_runtime/site/repository.py index 22b9a9c0..bbd7ae5e 100644 --- a/nmdc_runtime/site/repository.py +++ b/nmdc_runtime/site/repository.py @@ -405,9 +405,7 @@ def claim_and_run_apply_changesheet_jobs(_context): def done_object_put_ops(_context): client = get_runtime_api_site_client(run_config_frozen__normal_env) ops = [ - op.model_dump( - mode="json", - ) + op.model_dump() for op in client.list_operations( { "filter": json.dumps( diff --git a/nmdc_runtime/site/resources.py b/nmdc_runtime/site/resources.py index 983ab206..5f857a77 100644 --- a/nmdc_runtime/site/resources.py +++ b/nmdc_runtime/site/resources.py @@ -60,9 +60,7 @@ def request(self, method, url_path, params_or_json_data=None): self.ensure_token() kwargs = {"url": self.base_url + url_path, "headers": self.headers} if isinstance(params_or_json_data, BaseModel): - params_or_json_data = params_or_json_data.model_dump( - mode="json", exclude_unset=True - ) + params_or_json_data = params_or_json_data.model_dump(exclude_unset=True) if method.upper() == "GET": kwargs["params"] = params_or_json_data else: diff --git a/tests/integration/test_minter_repository.py b/tests/integration/test_minter_repository.py index 45ad0b56..2524ade4 100644 --- a/tests/integration/test_minter_repository.py +++ b/tests/integration/test_minter_repository.py @@ -31,9 +31,7 @@ def test_mint_and_resolve(): id_: Identifier = next(i for i in s.mint(req_mint)) req_res = ResolutionRequest( id_name=id_.name, - **req_mint.model_dump( - mode="json", - ), + **req_mint.model_dump(), ) assert s.resolve(req_res) is not None @@ -44,21 +42,10 @@ def test_mint_and_delete(): id_: Identifier = next(i for i in s.mint(req_mint)) req_del = DeleteRequest( id_name=id_.name, - **req_mint.model_dump( - mode="json", - ), + **req_mint.model_dump(), ) s.delete(req_del) - assert ( - s.resolve( - ResolutionRequest( - **req_del.model_dump( - mode="json", - ) - ) - ) - is None - ) + assert s.resolve(ResolutionRequest(**req_del.model_dump())) is None def test_mongo_mint_one(): @@ -91,9 +78,7 @@ def test_mongo_mint_and_resolve(): id_: Identifier = next(i for i in s.mint(req_mint)) req_res = ResolutionRequest( id_name=id_.name, - **req_mint.model_dump( - mode="json", - ), + **req_mint.model_dump(), ) assert s.resolve(req_res) is not None @@ -106,19 +91,8 @@ def test_mongo_mint_and_delete(): id_: Identifier = next(i for i in s.mint(req_mint)) req_del = DeleteRequest( id_name=id_.name, - **req_mint.model_dump( - mode="json", - ), + **req_mint.model_dump(), ) s.delete(req_del) - assert ( - s.resolve( - ResolutionRequest( - **req_del.model_dump( - mode="json", - ) - ) - ) - is None - ) + assert s.resolve(ResolutionRequest(**req_del.model_dump())) is None assert s.db["minter.id_records"].count_documents({}) == 0 diff --git a/tests/test_api/test_endpoints.py b/tests/test_api/test_endpoints.py index 387154b0..68a597ff 100644 --- a/tests/test_api/test_endpoints.py +++ b/tests/test_api/test_endpoints.py @@ -32,7 +32,7 @@ def ensure_test_resources(mdb): username=username, hashed_password=get_password_hash(password), site_admin=[site_id], - ).model_dump(mode="json", exclude_unset=True), + ).model_dump(exclude_unset=True), upsert=True, ) @@ -48,9 +48,7 @@ def ensure_test_resources(mdb): hashed_secret=get_password_hash(client_secret), ) ], - ).model_dump( - mode="json", - ), + ).model_dump(), upsert=True, ) wf_id = "test" @@ -59,7 +57,7 @@ def ensure_test_resources(mdb): mdb.operations.delete_many(prev_ops) job = Job(**{"id": job_id, "workflow": {"id": wf_id}, "config": {}, "claims": []}) mdb.jobs.replace_one( - {"id": job_id}, job.model_dump(mode="json", exclude_unset=True), upsert=True + {"id": job_id}, job.model_dump(exclude_unset=True), upsert=True ) return { "site_client": { @@ -68,7 +66,7 @@ def ensure_test_resources(mdb): "client_secret": client_secret, }, "user": {"username": username, "password": password}, - "job": job.model_dump(mode="json", exclude_unset=True), + "job": job.model_dump(exclude_unset=True), } @@ -124,7 +122,7 @@ def get_token(): "POST", url=(base_url + "/users"), headers=headers, - json=user_in.model_dump(mode="json", exclude_unset=True), + json=user_in.model_dump(exclude_unset=True), ) try: diff --git a/tests/test_graphs/ensure_jobs.py b/tests/test_graphs/ensure_jobs.py new file mode 100644 index 00000000..5a7359dd --- /dev/null +++ b/tests/test_graphs/ensure_jobs.py @@ -0,0 +1,26 @@ +import pytest +from toolz import merge + +from nmdc_runtime.site.graphs import ensure_jobs +from nmdc_runtime.site.repository import preset_normal + + +@pytest.skip("Needs supplied state") +def test_ensure_jobs(): + job = ensure_jobs.to_job(name="test_ensure_jobs", **preset_normal) + run_config = merge({}, preset_normal["config"]) + run_config["ops"] = { + "construct_jobs": { + "config": { + "base_jobs": [ + { + "config": {"object_id": "gfs03r29"}, + "workflow": {"id": "apply-changesheet-1.0"}, + } + ] + } + } + } + result = job.execute_in_process(run_config=run_config) + + assert result.success