126 lines
4.2 KiB
Python
126 lines
4.2 KiB
Python
# variable_substitution.py
|
|
#
|
|
# Copyright 2025 Pavel Baksy
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import re
|
|
from typing import Dict, List, Tuple, Set
|
|
from .models import HttpRequest, Environment
|
|
|
|
|
|
class VariableSubstitution:
|
|
"""Handles variable substitution with {{variable_name}} syntax."""
|
|
|
|
# Pattern to match {{variable_name}} where variable_name is alphanumeric + underscore
|
|
VARIABLE_PATTERN = re.compile(r'\{\{(\w+)\}\}')
|
|
|
|
@staticmethod
|
|
def find_variables(text: str) -> List[str]:
|
|
"""
|
|
Extract all {{variable_name}} references from text.
|
|
|
|
Args:
|
|
text: The text to search for variable references
|
|
|
|
Returns:
|
|
List of variable names found (without the {{ }} delimiters)
|
|
"""
|
|
if not text:
|
|
return []
|
|
return VariableSubstitution.VARIABLE_PATTERN.findall(text)
|
|
|
|
@staticmethod
|
|
def substitute(text: str, variables: Dict[str, str]) -> Tuple[str, List[str]]:
|
|
"""
|
|
Replace {{variable_name}} with values from variables dict.
|
|
|
|
Args:
|
|
text: The text containing variable placeholders
|
|
variables: Dictionary mapping variable names to their values
|
|
|
|
Returns:
|
|
Tuple of (substituted_text, list_of_undefined_variables)
|
|
"""
|
|
if not text:
|
|
return text, []
|
|
|
|
undefined_vars = []
|
|
|
|
def replace_var(match):
|
|
var_name = match.group(1)
|
|
if var_name in variables:
|
|
value = variables[var_name]
|
|
# Replace with value or empty string if value is None/empty
|
|
return value if value else ""
|
|
else:
|
|
# Variable not defined - track it and replace with empty string
|
|
undefined_vars.append(var_name)
|
|
return ""
|
|
|
|
substituted = VariableSubstitution.VARIABLE_PATTERN.sub(replace_var, text)
|
|
return substituted, undefined_vars
|
|
|
|
@staticmethod
|
|
def substitute_request(request: HttpRequest, environment: Environment) -> Tuple[HttpRequest, Set[str]]:
|
|
"""
|
|
Substitute variables in all request fields (URL, headers, body).
|
|
|
|
Args:
|
|
request: The HTTP request with variable placeholders
|
|
environment: The environment containing variable values
|
|
|
|
Returns:
|
|
Tuple of (new_request_with_substitutions, set_of_undefined_variables)
|
|
"""
|
|
all_undefined = set()
|
|
|
|
# Substitute URL
|
|
new_url, url_undefined = VariableSubstitution.substitute(
|
|
request.url, environment.variables
|
|
)
|
|
all_undefined.update(url_undefined)
|
|
|
|
# Substitute headers (both keys and values)
|
|
new_headers = {}
|
|
for key, value in request.headers.items():
|
|
new_key, key_undefined = VariableSubstitution.substitute(
|
|
key, environment.variables
|
|
)
|
|
new_value, value_undefined = VariableSubstitution.substitute(
|
|
value, environment.variables
|
|
)
|
|
all_undefined.update(key_undefined)
|
|
all_undefined.update(value_undefined)
|
|
new_headers[new_key] = new_value
|
|
|
|
# Substitute body
|
|
new_body, body_undefined = VariableSubstitution.substitute(
|
|
request.body, environment.variables
|
|
)
|
|
all_undefined.update(body_undefined)
|
|
|
|
# Create new HttpRequest with substituted values
|
|
new_request = HttpRequest(
|
|
method=request.method,
|
|
url=new_url,
|
|
headers=new_headers,
|
|
body=new_body,
|
|
syntax=request.syntax
|
|
)
|
|
|
|
return new_request, all_undefined
|