Skip to content

Sofia-Rdv/github-and-exchange-api

Repository files navigation

Python API services: GitHub & Currency Exchange

Python CI/CD

Обзор

Данный проект представляет собой набор инструментов для работы с внешними API(GitHub и ExchangeRate-API). Он включает в себя два сервиса: анализатор репозиториев GitHub и конвертер курсов валют.

Проект выполнен с соблюдением принципов модульности, надежной обработки ошибок и полного покрытия unit-тестами.

Функциональность

1. GitHub Repository Analyzer

  • Получение списка публичных репозиториев любого пользователя.
  • Анализ статистики: общее количество звезд, самый популярный репозиторий, распределение по языкам программирования.
  • Обработка специфических ошибок: "Пользователь не найден", "Превышение лимитов запросов API".

2. Currency Exchange Tool

  • Получение актуальных курсов валют относительно выбранной базы.
  • Фильтрация вывода по списку интересующих валют.
  • Надежная обработка сетевых сбоев, ошибок авторизации(401) и некорректных кодов валют.
  • Использование переменных окружения для безопасного хранения API-ключа.

Структура проекта

WorkWithAPI/
└── logging_module/
    ├── my_logger_config.py         # Модуль с настройками логирования и инициализацией логгеров
    ├── my_logging_config.yaml      # YAML-файл конфигурации для логирования
    └── my_color_formatter.py       # Кастомный форматтер для цветного вывода логов в консоль
└── logs/                           # Директория для логов
    └── task_1                      # Директория с файлами для логов первого задания
        ├── app.log                 # Информационные логи приложения
        └── error.log               # Логи ошибок и исключений
    └── task_2                      # Директория с файлами для логов второго задания
        ├── app.log                 # Информационные логи приложения
        └── error.log               # Логи ошибок и исключений
└── task_1_github_service/          # Директория с файлами программы первого задания
    ├── analytics.py                # Логика расчетов статистики (analyze_repos)
    ├── github_api.py               # Логика взаимодействия с GitHub (get_repos)
    ├── main.py                     # Запуск программы
    ├── test_github.py              # unit-тесты для analyze_repos и get_repos
└── task_2_exchangerate_service/    # Директория с файлами программы второго задания
    ├── exchangerate_api.py         # Логика взаимодействия с ExchangeRate-API (get_exchange_rates)
    ├── main_and_display_rates.py   # Запуск программы и функция вывода данных (display_rates)
    ├── test_exchangerate.py        # unit-тесты для get_exchange_rates и display_rates
├── .env.example                    # Пример переменной окружения
└── requirements.txt                # Список библиотек необходимых для работы программы

Начало работы

Требования

  • Python 3.10+
  • python-dotenv (для работы с переменной окружения)
  • requests (для работы с HTTP-запросами)
  • pytest и pytest-mock (для тестирования и имитации ответов сервера)
  • PyYAML (для загрузки конфигурации логирования)
  • Colorama - (для цветного вывода логов в консоль)

Установка

  1. Клонировать репозиторий:
git clone <URL_РЕПОЗИТОРИЯ>
cd <ИМЯ_ПАПКИ_ПРОЕКТА>
  1. Установить необходимые библиотеки (инструкцию см. ниже).
  2. Настроить API-ключ (инструкцию см. ниже).
  3. Запуск сервисов:
  • GitHub
python main.py
  • Currency Exchange
python main_and_display_rates.py

Инструкция по установке библиотек

  1. В командной строке или окне терминала ввести команду
  2. Нажать кнопку Enter

Команды для установки

  • pip install -r requirements.txt - Для установки всех библиотек

Инструкция по настройке API-ключей

Для работы сервиса конвертации валют (Currency Exchange Tool) необходимо получить API-ключ.

  1. Зарегистрируйтесь на сайте https://www.exchangerate-api.com/ и получите бесплатный ключ.
  2. Создайте в корневой директории проекта файл .env (или переименуйте пример)
  3. Добавьте в файл .env Ваш ключ в следующем формате
EXCHANGE_API_KEY=ваш_секретный_ключ

Важно: Никогда не фиксируйте файл .env в системе контроля версий (Git). Убедитесь, что он добавлен в Ваш .gitignore.


Система логирования

Приложение реализует комплексную систему логирования, которая:

  • Записывает все события приложения и ошибки.
  • Использует различные уровни логирования (INFO, WARNING, ERROR, DEBUG, CRITICAL).
  • Обеспечивает цветной вывод в консоль для лучшей читаемости.
  • Хранит логи в отдельных файлах(app.log для общей информации, error.log для ошибок) в общей директории logs/, но в разных папках для каждого задания.

Файлы логов

  • app.log: Содержит общую информацию о работе приложения, включая действия пользователя, успешное выполнение запросов к API и информационные сообщения.
  • error.log: Записывает все сообщения уровня ERROR и выше, включая ошибки выполнения запросов к API, исключения и критические сбои.

Компоненты логирования

Настройка системы логирования осуществляется через следующие файлы:

  • my_logger_config.py: Настраивает конфигурацию логирования
  • my_logging_config.yaml: Конфигурация для различных логгеров
  • my_color_formatter.py: Кастомный форматтер для цветного вывода в консоль

Тестирование

В проекте реализовано полное покрытие тестами всех модулей, включая успешные сценарии, сетевые ошибки (Timeout, ConnectionError) и ошибки бизнес-логики API.

Юнит-тесты с Pytest

Файл с тестированием можно запустить как и обычный код, через кнопку run.

Также юнит-тесты можно запустить из командной строки:

  • pytest - Краткий вариант результата юнит-тестов
  • pytest -v - Более детальный вывод результата юнит-тестов

Пример юнит-теста с Pytest из задания с сервисом GitHub

import pytest
import requests.exceptions
from pytest_mock import MockerFixture
from task_1_github_service.github_api import get_repos, GithubError, UserNotFoundError, RateLimitError
from task_1_github_service.analytics import analyze_repos


def test_analyze_repos_success():
    """
    Проверка успешного анализа списка репозиториев.
    Проверяет корректность подсчета звезд, общего количества и лучшего репозитория.
    """
    # Готовим тестовые данные (имитируем ответ от GitHub)
    test_data = [
        {"name": "repo1", "stargazers_count": 10, "language": "Python"},
        {"name": "repo2", "stargazers_count": 5, "language": "Python"},
        {"name": "repo3", "stargazers_count": 20, "language": "JavaScript"}
    ]

    stats = analyze_repos(test_data)

    assert stats['total_repos'] == 3
    assert stats['total_stars'] == 35
    assert stats['best_repo'] == ("repo3", 20)
    assert stats['languages'][0] == ("Python", 2)


def test_get_repos_timeout_error(mocker: MockerFixture):
    """
    Проверка обработки превышения времени ожидания.
    :param mocker: MockerFixture: Объект для имитации ошибок (mocking).
    """
    # Вместо возврата ответа, заставляем requests.get выбросить исключение Timeout
    mocker.patch("requests.get", side_effect=requests.exceptions.Timeout)

    with pytest.raises(GithubError) as excinfo:
        get_repos("testuser")

    # Проверяем, что в тексте ошибки есть нужные слова
    assert "Сервер GitHub слишком долго не отвечает" in str(excinfo.value)

Пример юнит-теста с Pytest из задания с сервисом ExchangeRate-API

import pytest
import requests
from pytest_mock import MockerFixture
from task_2_exchangerate_service.exchangerate_api import get_exchange_rates, CurrencyAPIError
from task_2_exchangerate_service.main_and_display_rates import display_rates


def test_get_exchange_rates_api_business_error(mocker: MockerFixture):
    """
    Проверка ошибки, которую возвращает сам API (unsupported-code).
    :param mocker: MockerFixture: Объект для имитации ответа от requests (mocking).
    """
    mock_resp = mocker.MagicMock()
    # API часто присылает 200, но с текстом ошибки внутри
    mock_resp.status_code = 200
    mock_resp.json.return_value = {
        "result": "error",
        "error-type": "unsupported-code"
    }
    mocker.patch("requests.get", return_value=mock_resp)

    with pytest.raises(CurrencyAPIError) as excinfo:
        get_exchange_rates("ABC")

    assert "не поддерживается сервисом" in str(excinfo.value)


@pytest.mark.parametrize("setup_type", ["valid_code", "invalid_codes_all"])
def test_display_rates_with_invalid_codes(capsys: pytest.CaptureFixture, setup_type: str):
    """
    Проверка вывода сообщения о некорректных кодах.
    :param capsys: pytest.CaptureFixture: Фикстура pytest для перехвата и анализа вывода данных.
    :param setup_type: str: Ключ сценария подготовки данных (из parametrize).
    """
    data = {
        "base_code": "USD",
        "conversion_rates": {"EUR": 0.84}
    }

    if setup_type == "valid_code":
        # EUR - корректно, WWW - нет
        target_currencies = ["EUR", "WWW"]
        expected_text = "[!] Не удалось найти или некорректные коды валют: WWW"

    elif setup_type == "invalid_codes_all":
        # Все не корректные
        target_currencies = ["AAA", "RUS", "888"]
        expected_text = "[!] Ни одна из указанных валют не была найдена."

    display_rates(data, target_currencies)

    captured = capsys.readouterr()
    assert expected_text in captured.out

    if setup_type == "valid_code":
        assert "1 USD = 0.84 EUR" in captured.out
        assert expected_text in captured.out

About

Практический проект на Python для работы с API. Включает два инструмента: получение информации о пользователях GitHub и конвертер валют с использованием актуальных курсов.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages