Conditional Logic in YAML with Python (Custom Loading)

This tutorial will guide you through several methods to implement conditional logic in YAML using Python.

We’ll use template engines like Jinja2, custom YAML tags, and combine YAML with Python classes.

 

 

Using Jinja2 with YAML for Conditional Logic

You can use Jinja2 to introduce conditional statements within your YAML files which allows dynamic configuration based on variables.

import yaml
from jinja2 import Template
yaml_template = """
user: {{ name }}
role: {% if admin %}admin{% else %}user{% endif %}
permissions:
  - read
  {% if admin %}
  - write
  - delete
  {% endif %}
"""
template = Template(yaml_template)
rendered = template.render(name="Mona", admin=True)
config = yaml.safe_load(rendered)
print(config)

Output:

{'user': 'Mona', 'role': 'admin', 'permissions': ['read', 'write', 'delete']}

Here, Jinja2 processes the YAML template to include additional permissions if the user is an admin.

 

Using Custom Tags and YAML Constructors

Creating custom tags in YAML allows for more conditional processing when combined with Python constructors.

import yaml
class DeferredIf:
    def __init__(self, condition, true_val, false_val):
        self.condition = condition
        self.true_val = true_val
        self.false_val = false_val

def if_constructor(loader, node):
    value = loader.construct_sequence(node)
    if len(value) != 3:
        raise yaml.constructor.ConstructorError(
            None, None,
            "!if tag requires exactly three arguments",
            node.start_mark)
    return DeferredIf(*value)

class CustomLoader(yaml.SafeLoader):
    pass

CustomLoader.add_constructor('!if', if_constructor)
yaml_data = """
environment: production
debug_mode: !if [environment == 'production', false, true]
"""
config = yaml.load(yaml_data, Loader=CustomLoader)
for key, value in config.items():
    if isinstance(value, DeferredIf):
        condition = value.condition.replace('environment', f"config['environment']")
        config[key] = value.true_val if eval(condition) else value.false_val
print(config)

Output:

{'environment': 'production', 'debug_mode': False}

This example defines a custom !if tag to conditionally set debug_mode based on the environment.

 

Combine YAML with Python Classes

Integrating Python classes with YAML allows you to manage conditional configurations through object-oriented programming.

import yaml
class Config:
    def __init__(self, environment):
        self.environment = environment
        self.settings = self.load_settings()
    def load_settings(self):
        with open('config.yaml') as f:
            data = yaml.safe_load(f)
        env_config = data.get(self.environment, {})
        return env_config
config = Config(environment='development')
print(config.settings)

The config.yaml file:

development:
  debug: true
  database:
    host: dev.db.local
    port: 5432

production:
  debug: false
  database:
    host: prod.db.server
    port: 5432

Output:

{'debug': True, 'database': {'host': 'dev.db.local', 'port': 5432}}

By using a Python class to load configurations based on the environment, you allow conditional logic that adjusts settings dynamically.

Leave a Reply

Your email address will not be published. Required fields are marked *