From 51ec9765626b2523101977dc7f7a6186dbd8d496 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sun, 5 Oct 2025 13:59:58 +0200 Subject: [PATCH] Fix a quoting problem related to CCDB remapping The CCDB remapping arguments appeared sometimes correctly quoted and in some cases not. This is because the task_finalizer reapplied string construction/quoting which was not generic enough. This is fixed with this commit. In addition, we now automatically quote ALIEN_JDL_REMAPPING if needed. Both versions ``` export ALIEN_JDL_REMAPPING="foo;bar" ``` as well as (quoted) ``` export ALIEN_JDL_REMAPPING='"foo;bar"' ``` will work. It is recommended to just use the former. --- MC/bin/o2dpg_dpl_config_tools.py | 23 +++++++++++++++++------ MC/bin/o2dpg_sim_workflow.py | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/MC/bin/o2dpg_dpl_config_tools.py b/MC/bin/o2dpg_dpl_config_tools.py index 26dbfbf86..388e4306f 100755 --- a/MC/bin/o2dpg_dpl_config_tools.py +++ b/MC/bin/o2dpg_dpl_config_tools.py @@ -161,6 +161,23 @@ def log_line(logger, message): else: logger.write(message + "\n") +def quote_for_nested_string(val): + s = str(val) + # Already double-quoted? + if s.startswith('"') and s.endswith('"'): + return s + # Escape inner quotes + s_escaped = s.replace('"', r'\"') + return f'"{s_escaped}"' + +def quote_if_needed(val): + # Only quote values that are likely to break shell parsing + # or contain nested shell-sensitive characters + s = str(val) + if re.search(r'[ \t;:&|<>]', s): + return quote_for_nested_string(s) + return s + def modify_dpl_command(cmd_str, config_anchor, allow_overwrite=False, logger=None, configname=None): # check if cmd_str is given as list, in which case we transfrom to string if isinstance(cmd_str, list) == True: @@ -196,12 +213,6 @@ def modify_dpl_command(cmd_str, config_anchor, allow_overwrite=False, logger=Non added = [] overwritten = [] - def quote_if_needed(val): - s = str(val) - if " " in s and not (s.startswith('"') and s.endswith('"')): - return f'"{s}"' - return s - # Step 1: Existing options (preserved or overwritten) for key, val in existing_opts.items(): if allow_overwrite and key in anchor_opts: diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index d54fce527..5431429a3 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -43,7 +43,7 @@ from o2dpg_workflow_utils import createTask, createGlobalInitTask, dump_workflow, adjust_RECO_environment, isActive, activate_detector, deactivate_detector, compute_n_workers, merge_dicts from o2dpg_qc_finalization_workflow import include_all_QC_finalization from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available, overwrite_config -from o2dpg_dpl_config_tools import parse_command_string, modify_dpl_command, dpl_option_from_config, TaskFinalizer +from o2dpg_dpl_config_tools import dpl_option_from_config, TaskFinalizer, quote_if_needed # for some JAliEn interaction from alienpy.alien import JAlien @@ -504,7 +504,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): if ccdbbackend: common=common + " --condition-not-after " + str(args.condition_not_after) if ccdbRemap != None: - common=common + " --condition-remap " + ccdbRemap + common=common + f" --condition-remap {quote_if_needed(ccdbRemap)} " if args.noIPC!=None: return common + " --no-IPC " if bigshm: