/
tinypot
/
integr3
Обзор
Документация
Войти
/
tinypot
/
integr3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
client/main.py
221 строка
9 KB
Tim Polus
lab3: клиент для интеграции с Task Tracker API
02 мар 2026, 05:56
02 мар 2026, 05:56
c4962cb
Код
Авторство
О чём код?
#!/usr/bin/env python3 """ Интерактивный CLI-клиент для Task Tracker API. Демонстрирует все основные операции: - Аутентификация (JWT) - CRUD проектов - CRUD задач (v1) - Создание задач v2 (с приоритетом) - Идемпотентные POST-запросы - Пагинация - Обработка ошибок и rate-limit """ from __future__ import annotations import json import sys import uuid from api_client import TaskTrackerClient def pp(data) -> None: """Pretty-print JSON-подобных объектов.""" print(json.dumps(data, indent=2, ensure_ascii=False, default=str)) def show_menu() -> None: print( """ ╔══════════════════════════════════════════════╗ ║ Task Tracker CLI Client ║ ╠══════════════════════════════════════════════╣ ║ Проекты (v1) ║ ║ 1 — Список проектов ║ ║ 2 — Получить проект по ID ║ ║ 3 — Создать проект ║ ║ 4 — Обновить проект ║ ║ 5 — Удалить проект ║ ╠══════════════════════════════════════════════╣ ║ Задачи (v1) ║ ║ 6 — Список задач (пагинация) ║ ║ 7 — Все задачи (автопагинация) ║ ║ 8 — Получить задачу по ID ║ ║ 9 — Создать задачу (идемпотентно) ║ ║ 10 — Обновить задачу ║ ║ 11 — Удалить задачу ║ ╠══════════════════════════════════════════════╣ ║ Задачи (v2 — с приоритетом) ║ ║ 12 — Список задач v2 ║ ║ 13 — Создать задачу v2 (идемпотентно) ║ ╠══════════════════════════════════════════════╣ ║ Прочее ║ ║ 14 — Статистика (admin) ║ ║ 15 — Демо: идемпотентность ║ ║ 0 — Выход ║ ╚══════════════════════════════════════════════╝""" ) def prompt(msg: str, default: str = "") -> str: if default: val = input(f"{msg} [{default}]: ").strip() return val or default return input(f"{msg}: ").strip() def prompt_int(msg: str, default: int | None = None) -> int: raw = prompt(msg, str(default) if default is not None else "") return int(raw) def run_demo_idempotency(client: TaskTrackerClient) -> None: """Демонстрация идемпотентности: два POST с одинаковым ключом.""" projects = client.get_projects() if not projects: print("Нет проектов. Создайте хотя бы один проект.") return project_id = projects[0]["id"] key = str(uuid.uuid4()) print(f"\nИспользуем Idempotency-Key: {key}") print(f"Проект ID: {project_id}\n") print(">>> Первый запрос POST /api/v1/tasks:") task1 = client.create_task("Idempotent task test", project_id, idempotency_key=key) pp(task1) print("\n>>> Повторный запрос с тем же ключом:") task2 = client.create_task("Idempotent task test", project_id, idempotency_key=key) pp(task2) same = task1.get("id") == task2.get("id") if isinstance(task2, dict) else False print(f"\nID совпадают: {same} — задача НЕ продублировалась" if same else "") def main() -> None: client = TaskTrackerClient() print("Аутентификация...") try: token_info = client.authenticate() print(f"Успешно. Тип: {token_info.get('token_Type', 'Bearer')}, " f"Истекает через: {token_info.get('expires_In_Seconds', '?')}с") except Exception as e: print(f"Ошибка аутентификации: {e}") sys.exit(1) while True: show_menu() choice = prompt("\nВыберите команду", "0") try: if choice == "0": print("Выход.") break elif choice == "1": projects = client.get_projects() print(f"\nПроектов: {len(projects)}") pp(projects) elif choice == "2": pid = prompt_int("ID проекта") pp(client.get_project(pid)) elif choice == "3": name = prompt("Название проекта") result = client.create_project(name) print("Создан:") pp(result) elif choice == "4": pid = prompt_int("ID проекта") name = prompt("Новое название") client.update_project(pid, name) print(f"Проект {pid} обновлён.") elif choice == "5": pid = prompt_int("ID проекта") client.delete_project(pid) print(f"Проект {pid} удалён.") elif choice == "6": page = prompt_int("Страница", 1) size = prompt_int("Размер страницы", 10) data = client.get_tasks(page=page, page_size=size) print(f"Страница {data.get('page')}/{-(-data.get('totalCount', 0) // size)}, " f"всего: {data.get('totalCount')}") pp(data.get("items", [])) elif choice == "7": tasks = client.get_all_tasks() print(f"\nВсего задач: {len(tasks)}") pp(tasks) elif choice == "8": tid = prompt_int("ID задачи") inc = prompt("Включить проект? (y/n)", "n").lower() == "y" pp(client.get_task(tid, include_project=inc)) elif choice == "9": title = prompt("Название задачи") pid = prompt_int("ID проекта") use_key = prompt("Задать Idempotency-Key вручную? (y/n)", "n") key = prompt("Idempotency-Key") if use_key.lower() == "y" else None result = client.create_task(title, pid, idempotency_key=key) print("Создана:") pp(result) elif choice == "10": tid = prompt_int("ID задачи") title = prompt("Новое название (Enter — не менять)") or None done_raw = prompt("isDone (true/false/Enter — не менять)") is_done = None if done_raw.lower() in ("true", "false"): is_done = done_raw.lower() == "true" result = client.update_task(tid, title=title, is_done=is_done) print("Обновлена:") pp(result) elif choice == "11": tid = prompt_int("ID задачи") client.delete_task(tid) print(f"Задача {tid} удалена.") elif choice == "12": page = prompt_int("Страница", 1) size = prompt_int("Размер страницы", 10) data = client.get_tasks_v2(page=page, page_size=size) print(f"v2 | Страница {data.get('page')}, всего: {data.get('totalCount')}") pp(data.get("items", [])) elif choice == "13": title = prompt("Название задачи") pid = prompt_int("ID проекта") priority_raw = prompt("Приоритет (число, Enter — пропустить)") priority = int(priority_raw) if priority_raw else None result = client.create_task_v2(title, pid, priority=priority) print("Создана (v2):") pp(result) elif choice == "14": pp(client.get_stats()) elif choice == "15": run_demo_idempotency(client) else: print("Неизвестная команда.") except KeyboardInterrupt: print("\nПрервано.") break except Exception as e: print(f"\nОшибка: {e}") if __name__ == "__main__": main()