import time
from typing import NamedTuple, Optional
class ReturnFromPostProcessor(NamedTuple):
is_operation_successful: bool
next_operation_id: Optional[str]
local_vars: dict
global_vars: dict
def post_processor(
response, operation, user_vars, listener, user_class, *args, **kwargs
) -> ReturnFromPostProcessor:
# Инициализируем дефолтные значения на случай полной деградации user_vars
current_iter = 0
total_iter = 1
num_a = 0.0
num_b = 0.0
# ОПТИМИЗАЦИЯ 1: Быстрое и безопасное извлечение переменных в один проход
try:
if isinstance(user_vars, dict):
it = user_vars.get('iteration')
tot = user_vars.get('total_iterations')
na = user_vars.get('numA')
nb = user_vars.get('numB')
# Извлекаем значения вне зависимости от того, объект это UserVar или сырой тип
if it is not None: current_iter = int(it.value if hasattr(it, 'value') else it)
if tot is not None: total_iter = int(tot.value if hasattr(tot, 'value') else tot)
if na is not None: num_a = float(na.value if hasattr(na, 'value') else na)
if nb is not None: num_b = float(nb.value if hasattr(nb, 'value') else nb)
except (ValueError, TypeError, AttributeError):
pass # При любых аномалиях данных безопасно работаем с дефолтами
# Вычисляем флаг завершения цикла заранее
remaining = current_iter < (total_iter - 1)
is_success = False
# ОПТИМИЗАЦИЯ 2: Безопасная проверка статус-кодов (200 или 204) без риска NoneType
if hasattr(response, "status_code") and response.status_code in (200, 204):
is_success = True
# Расчет и подача пэйсинга (только при успешном запросе и наличии следующих итераций)
if remaining:
try:
pacing = (((num_b + num_a) / 2) - 15) / total_iter
if pacing > 0:
time.sleep(pacing)
except (ZeroDivisionError, ValueError, TypeError):
pass # Если total_iter равен 0 или данные побились — просто идем дальше
# ОПТИМИЗАЦИЯ 3: Плоская матрица возврата (исключает дублирование веток кода)
if is_success and remaining:
return ReturnFromPostProcessor(
True,
"UC01_POST_spending_WEB",
{"iteration": str(current_iter + 1)},
{}
)
# Сюда мы попадаем, если:
# 1. Запрос успешен, но это была последняя итерация цикла.
# 2. Запрос завершился ошибкой (код не 200/204).
# В обоих случаях по вашей логике мы сбрасываем итератор в "0" и возвращаем next_operation_id = None
return ReturnFromPostProcessor(is_success, None, {"iteration": "0"}, {})