44# https://opensource.org/licenses/MIT.
55
66import copy
7- import json
87import logging
98from datetime import datetime
109from pathlib import Path
1110
1211import fsspec
12+ import jsonpickle
1313import yaml
1414from pystac import Catalog , Link
1515
2222)
2323from deep_code .utils .dataset_stac_generator import OscDatasetStacGenerator
2424from deep_code .utils .github_automation import GitHubAutomation
25- from deep_code .utils .helper import serialize
2625from deep_code .utils .ogc_api_record import (
2726 ExperimentAsOgcRecord ,
2827 LinksBuilder ,
@@ -130,6 +129,7 @@ def __init__(
130129 self ._read_config_files ()
131130 self .collection_id = self .dataset_config .get ("collection_id" )
132131 self .workflow_title = self .workflow_config .get ("properties" , {}).get ("title" )
132+ self .workflow_id = self .workflow_config .get ("workflow_id" )
133133
134134 if not self .collection_id :
135135 raise ValueError ("collection_id is missing in dataset config." )
@@ -151,11 +151,12 @@ def _write_to_file(file_path: str, data: dict):
151151 # Create the directory if it doesn't exist
152152 Path (file_path ).parent .mkdir (parents = True , exist_ok = True )
153153 try :
154- json_content = json .dumps (data , indent = 2 , default = serialize )
154+ # unpicklable=False -> plain JSON (drops type metadata); cycles are resolved.
155+ json_content = jsonpickle .encode (data , unpicklable = False , indent = 2 )
155156 except TypeError as e :
156157 raise RuntimeError (f"JSON serialization failed: { e } " )
157158
158- with open (file_path , "w" ) as f :
159+ with open (file_path , "w" , encoding = "utf-8" ) as f :
159160 f .write (json_content )
160161
161162 def _update_and_add_to_file_dict (
@@ -217,6 +218,7 @@ def publish_dataset(self, write_to_file: bool = False):
217218 osc_region = self .dataset_config .get ("osc_region" )
218219 osc_themes = self .dataset_config .get ("osc_themes" )
219220 cf_params = self .dataset_config .get ("cf_parameter" )
221+ license_type = self .dataset_config .get ("license_type" )
220222
221223 if not dataset_id or not self .collection_id :
222224 raise ValueError ("Dataset ID or Collection ID missing in the config." )
@@ -226,6 +228,9 @@ def publish_dataset(self, write_to_file: bool = False):
226228 generator = OscDatasetStacGenerator (
227229 dataset_id = dataset_id ,
228230 collection_id = self .collection_id ,
231+ workflow_id = self .workflow_id ,
232+ workflow_title = self .workflow_title ,
233+ license_type = license_type ,
229234 documentation_link = documentation_link ,
230235 access_link = access_link ,
231236 osc_status = dataset_status ,
@@ -310,7 +315,7 @@ def _update_base_catalog(
310315
311316 return base_catalog
312317
313- def publish_workflow_experiment (self , write_to_file : bool = False ):
318+ def generate_workflow_experiment_records (self , write_to_file : bool = False ) -> None :
314319 """prepare workflow and experiment as ogc api record to publish it to the
315320 specified GitHub repository."""
316321 workflow_id = self ._normalize_name (self .workflow_config .get ("workflow_id" ))
@@ -328,16 +333,23 @@ def publish_workflow_experiment(self, write_to_file: bool = False):
328333 wf_record_properties = rg .build_record_properties (properties_list , contacts )
329334 # make a copy for experiment record
330335 exp_record_properties = copy .deepcopy (wf_record_properties )
336+ jupyter_kernel_info = wf_record_properties .jupyter_kernel_info .to_dict ()
331337
332- link_builder = LinksBuilder (osc_themes )
338+ link_builder = LinksBuilder (osc_themes , jupyter_kernel_info )
333339 theme_links = link_builder .build_theme_links_for_records ()
340+ application_link = link_builder .build_link_to_jnb (
341+ self .workflow_title , jupyter_notebook_url
342+ )
343+ jnb_open_link = link_builder .make_related_link_for_opening_jnb_from_github (
344+ jupyter_notebook_url = jupyter_notebook_url
345+ )
334346
335347 workflow_record = WorkflowAsOgcRecord (
336348 id = workflow_id ,
337349 type = "Feature" ,
338350 title = self .workflow_title ,
339351 properties = wf_record_properties ,
340- links = links + theme_links ,
352+ links = links + theme_links + application_link + jnb_open_link ,
341353 jupyter_notebook_url = jupyter_notebook_url ,
342354 themes = osc_themes ,
343355 )
@@ -347,21 +359,24 @@ def publish_workflow_experiment(self, write_to_file: bool = False):
347359 del workflow_dict ["jupyter_notebook_url" ]
348360 if "osc_workflow" in workflow_dict ["properties" ]:
349361 del workflow_dict ["properties" ]["osc_workflow" ]
362+ # add workflow record to file_dict
350363 wf_file_path = f"workflows/{ workflow_id } /record.json"
351364 file_dict = {wf_file_path : workflow_dict }
352365
353366 # Build properties for the experiment record
354367 exp_record_properties .type = "experiment"
355368 exp_record_properties .osc_workflow = workflow_id
356369
370+ dataset_link = link_builder .build_link_to_dataset (self .collection_id )
371+
357372 experiment_record = ExperimentAsOgcRecord (
358373 id = workflow_id ,
359374 title = self .workflow_title ,
360375 type = "Feature" ,
361376 jupyter_notebook_url = jupyter_notebook_url ,
362377 collection_id = self .collection_id ,
363378 properties = exp_record_properties ,
364- links = links + theme_links ,
379+ links = links + theme_links + dataset_link ,
365380 )
366381 # Convert to dictionary and cleanup
367382 experiment_dict = experiment_record .to_dict ()
@@ -371,6 +386,7 @@ def publish_workflow_experiment(self, write_to_file: bool = False):
371386 del experiment_dict ["collection_id" ]
372387 if "osc:project" in experiment_dict ["properties" ]:
373388 del experiment_dict ["properties" ]["osc:project" ]
389+ # add experiment record to file_dict
374390 exp_file_path = f"experiments/{ workflow_id } /record.json"
375391 file_dict [exp_file_path ] = experiment_dict
376392
@@ -397,7 +413,9 @@ def publish_all(self, write_to_file: bool = False):
397413 """Publish both dataset and workflow/experiment in a single PR."""
398414 # Get file dictionaries from both methods
399415 dataset_files = self .publish_dataset (write_to_file = write_to_file )
400- workflow_files = self .publish_workflow_experiment (write_to_file = write_to_file )
416+ workflow_files = self .generate_workflow_experiment_records (
417+ write_to_file = write_to_file
418+ )
401419
402420 # Combine the file dictionaries
403421 combined_files = {** dataset_files , ** workflow_files }
0 commit comments