Загрузка данных


# --- Кастомные исключения ---

class MissingEqualsError(Exception):
    """Строка не содержит символ '='"""
    def __init__(self):
        super().__init__("отсутствует символ \"=\"")


class EmptyKeyError(Exception):
    """Ключ пустой (строка начинается с =)"""
    def __init__(self):
        super().__init__("ключ не может быть пустым")


class DuplicateKeyError(Exception):
    """Такой ключ уже был добавлен ранее"""
    def __init__(self, key):
        self.key = key
        super().__init__(f"ключ \"{key}\" уже существует")


# --- Функции парсинга ---

def parse_line(line: str, existing: dict):
    """
    Парсит одну строку конфигурации и добавляет пару в словарь.
    Игнорирует пустые строки и комментарии (начинаются с #).
    """
    # Удаляем лишние пробелы по краям строки
    stripped = line.strip()
    
    # Игнорируем пустые строки и комментарии
    if not stripped or stripped.startswith('#'):
        return

    # Проверка на наличие знака равенства
    if '=' not in stripped:
        raise MissingEqualsError()

    # Разделяем по первому знаку '='
    key, value = stripped.split('=', 1)
    key = key.strip()
    value = value.strip()

    # Проверка на пустой ключ
    if not key:
        raise EmptyKeyError()

    # Проверка на дубликат ключа
    if key in existing:
        raise DuplicateKeyError(key)

    # Если всё хорошо, добавляем в словарь
    existing[key] = value


def parse_config(lines: list) -> tuple:
    """
    Вызывает parse_line для каждой строки.
    Собирает все проблемные строки с их номерами (начиная с 1) и описанием ошибок.
    Возвращает кортеж (словарь, список_ошибок).
    """
    config = {}
    errors = []

    for index, line in enumerate(lines, start=1):
        try:
            parse_line(line, config)
        except (MissingEqualsError, EmptyKeyError, DuplicateKeyError) as err:
            # Форматируем вывод ошибки согласно примеру из задания
            error_class_name = err.__class__.__name__
            errors.append(f"Строка {index}: {error_class_name} — {err}")
            
    return config, errors


# --- Тестирование (Пример работы из задания) ---

if __name__ == "__main__":
    lines = [
        "# Настройки приложения",
        "host=localhost",
        "port=8080",
        "portинтерфейс",   # нет знака =
        "=admin",          # пустой ключ
        "host=remotehost",  # дубликат
        "",
        "timeout=30"
    ]

    config, errors = parse_config(lines)

    print("Результат парсинга (config):")
    print(config)
    # Ожидается: {'host': 'localhost', 'port': '8080', 'timeout': '30'}

    print("\nОбнаруженные ошибки (errors):")
    for err in errors:
        print(err)
    # Ожидается:
    # Строка 4: MissingEqualsError — отсутствует символ "="
    # Строка 5: EmptyKeyError — ключ не может быть пустым
    # Строка 6: DuplicateKeyError — ключ "host" уже существует