Python Forum
Replace values in Yaml file with value in dictionary
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Replace values in Yaml file with value in dictionary
#1
Hi, I have a problem with one script. (Python3 ver 3.6.x)
I have a file "deployment_custom.txt" containing values to set in a Yaml file. One value per line.
Then I have the Yaml file, "deployment.yml".

Here are a snippet from "deployment_custom.txt"
Quote:spec components synapse config postgresql port 123
spec components synapse config delegatedAuth oidc clientID q11xxx

Here are a snippet from "deployment.yml"
spec:
  components:
    synapse:
      config:
        delegatedAuth:
          oidc:
            - backchannelLogoutEnabled: true
              clientId: 111111111111
              idpId: proxy1
        postgresql:
          database: synapse
          host: postgresql
          passwordSecretKey: postgresPassword
          sslMode: disable
          user: syn_user
          port: 5436[/quote]
My script do fix the first line "port 123".
The problem starts with the dictionary oidc containing clientId. How to update that value?

from ruamel.yaml import YAML
import sys

def load_custom_values(file_path):
    with open(file_path, "r") as custom_file:
        return [line.strip() for line in custom_file]

def load_yaml(file_path):
    yaml = YAML()
    with open(file_path, "r") as yaml_file:
        return yaml.load(yaml_file)

def edit_yaml(data, keys, new_value):
    if len(keys) == 1:
        data[keys[0]] = int(new_value) if new_value.isdigit() else new_value
    else:
        edit_yaml(data[keys[0]], keys[1:], new_value)

def apply_custom_values(yaml_data, custom_values):
    for custom_value in custom_values:
        parts = custom_value.split()
        if len(parts) >= 3:
            section = parts[0]
            if section in yaml_data:
                keys = parts[1:-1]
                new_value = parts[-1]
                edit_yaml(yaml_data[section], keys, new_value)
    return yaml_data

def save_yaml(data, file_path):
    yaml = YAML()
    yaml.indent(mapping=2, sequence=4, offset=2)  # Ensure proper indentation
    with open(file_path, "w") as modified_file:
        yaml.dump(data, modified_file)

def fix_deployment_file(org):
    custom_file_path = f"./{org}/deployment_custom.txt"
    yaml_file_path = f"./{org}/deployment.yml"

    custom_values = load_custom_values(custom_file_path)
    yaml_data = load_yaml(yaml_file_path)
    modified_yaml_data = apply_custom_values(yaml_data, custom_values)
    save_yaml(modified_yaml_data, yaml_file_path)

if __name__ == "__main__":
    org = sys.argv[1] if len(sys.argv) > 1 else None
    if not org:
        print("Please provide the name of ORG.")
        sys.exit(1)
    fix_deployment_file(org)
How to solve the problematic part with dictionary values?

/Pelle
alexjordan likes this post
Reply
#2
(Jun-12-2024, 02:40 PM)PelleH Wrote: Hi, I have a problem with one script. (Python3 ver 3.6.x)
I have a file "deployment_custom.txt" containing values to set in a Yaml file. One value per line.
Then I have the Yaml file, "deployment.yml".

Here are a snippet from "deployment_custom.txt"
Quote:spec components synapse config postgresql port 123
spec components synapse config delegatedAuth oidc clientID q11xxx

Here are a snippet from "deployment.yml"
spec:
  components:
    synapse:
      config:
        delegatedAuth:
          oidc:
            - backchannelLogoutEnabled: true
              clientId: 111111111111
              idpId: proxy1
        postgresql:
          database: synapse
          host: postgresql
          passwordSecretKey: postgresPassword
          sslMode: disable
          user: syn_user
          port: 5436[/quote]
My script do fix the first line "port 123".
The problem starts with the dictionary oidc containing clientId. How to update that value?

from ruamel.yaml import YAML
import sys

def load_custom_values(file_path):
    with open(file_path, "r") as custom_file:
        return [line.strip() for line in custom_file]

def load_yaml(file_path):
    yaml = YAML()
    with open(file_path, "r") as yaml_file:
        return yaml.load(yaml_file)

def edit_yaml(data, keys, new_value):
    if len(keys) == 1:
        data[keys[0]] = int(new_value) if new_value.isdigit() else new_value
    else:
        edit_yaml(data[keys[0]], keys[1:], new_value)

def apply_custom_values(yaml_data, custom_values):
    for custom_value in custom_values:
        parts = custom_value.split()
        if len(parts) >= 3:
            section = parts[0]
            if section in yaml_data:
                keys = parts[1:-1]
                new_value = parts[-1]
                edit_yaml(yaml_data[section], keys, new_value)
    return yaml_data

def save_yaml(data, file_path):
    yaml = YAML()
    yaml.indent(mapping=2, sequence=4, offset=2)  # Ensure proper indentation
    with open(file_path, "w") as modified_file:
        yaml.dump(data, modified_file)

def fix_deployment_file(org):
    custom_file_path = f"./{org}/deployment_custom.txt"
    yaml_file_path = f"./{org}/deployment.yml"

    custom_values = load_custom_values(custom_file_path)
    yaml_data = load_yaml(yaml_file_path)
    modified_yaml_data = apply_custom_values(yaml_data, custom_values)
    save_yaml(modified_yaml_data, yaml_file_path)

if __name__ == "__main__":
    org = sys.argv[1] if len(sys.argv) > 1 else None
    if not org:
        print("Please provide the name of ORG.")
        sys.exit(1)
    fix_deployment_file(org)
How to solve the problematic part with dictionary values?

/Pelle

I have done somewhat similar for one of the , where nested dictionaries, such as oidc: clientId, need updating dynamically, modifying YAML files using Python can streamline the process. Below is an improved version of your script that correctly updates nested dictionary values:

Updated Python Solution
python
Copy
Edit
from ruamel.yaml import YAML
import sys

def load_custom_values(file_path):
    with open(file_path, "r") as custom_file:
        return [line.strip().split() for line in custom_file if line.strip()]

def load_yaml(file_path):
    yaml = YAML()
    with open(file_path, "r") as yaml_file:
        return yaml.load(yaml_file)

def edit_yaml(data, keys, new_value):
    """Recursively updates YAML nested dictionaries."""
    if len(keys) == 1:
        data[keys[0]] = int(new_value) if new_value.isdigit() else new_value
    elif isinstance(data.get(keys[0]), list):  
        for item in data[keys[0]]:  
            if isinstance(item, dict) and keys[1] in item:
                item[keys[1]] = new_value  
    else:
        edit_yaml(data[keys[0]], keys[1:], new_value)

def apply_custom_values(yaml_data, custom_values):
    for parts in custom_values:
        if len(parts) >= 3:
            keys = parts[:-1]  # All elements except the last one are keys
            new_value = parts[-1]  # Last element is the value
            edit_yaml(yaml_data, keys, new_value)
    return yaml_data

def save_yaml(data, file_path):
    yaml = YAML()
    yaml.indent(mapping=2, sequence=4, offset=2)  # Ensure proper indentation
    with open(file_path, "w") as modified_file:
        yaml.dump(data, modified_file)

def fix_deployment_file(org):
    custom_file_path = f"./{org}/deployment_custom.txt"
    yaml_file_path = f"./{org}/deployment.yml"

    custom_values = load_custom_values(custom_file_path)
    yaml_data = load_yaml(yaml_file_path)
    modified_yaml_data = apply_custom_values(yaml_data, custom_values)
    save_yaml(modified_yaml_data, yaml_file_path)

if __name__ == "__main__":
    org = sys.argv[1] if len(sys.argv) > 1 else None
    if not org:
        print("Please provide the name of ORG.")
        sys.exit(1)
    fix_deployment_file(org)
This script ensures that even deeply nested YAML structures can be updated dynamically, preventing configuration errors that could disrupt automated systems.
Larz60+ write Feb-11-2025, 09:56 AM:
additional spam link removed
buran write Feb-10-2025, 07:51 PM:
spam link removed
Please, use proper tags when post code, traceback, output, etc. This time I have added tags for you.
See BBcode help for more info.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  I'm assuming you're asking about accessing nested dictionary keys and values in Pytho DavidSah 0 580 Dec-18-2025, 01:54 AM
Last Post: DavidSah
Question [SOLVED] Access keys and values from nested dictionary? Winfried 4 914 Nov-17-2025, 11:47 AM
Last Post: Winfried
Question [SOLVED] [Beautiful Soup] Replace tag.string from another file? Winfried 2 1,673 May-01-2025, 03:43 PM
Last Post: Winfried
Question Using Lists as Dictionary Values bfallert 8 3,938 Apr-21-2024, 06:55 AM
Last Post: Pedroski55
  need to compare 2 values in a nested dictionary jss 2 2,974 Nov-30-2023, 03:17 PM
Last Post: Pedroski55
  Replace a text/word in docx file using Python Devan 4 44,842 Oct-17-2023, 06:03 PM
Last Post: Devan
  Need to replace a string with a file (HTML file) tester_V 1 3,016 Aug-30-2023, 03:42 AM
Last Post: Larz60+
  Printing specific values out from a dictionary mcoliver88 6 3,856 Apr-12-2023, 08:10 PM
Last Post: deanhystad
  Replace columns indexes reading a XSLX file Larry1888 2 2,514 Nov-18-2022, 10:16 PM
Last Post: Pedroski55
  How to do a mass replace within a CSV file? cubangt 9 11,255 May-09-2022, 06:52 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020