Skip to content

Task #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 174 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,197 @@ GraphQL API Gateway
Зависимости
===========

Установите требуемое ПО:

1. Docker для контейнеризации – |link_docker|

.. |link_docker| raw:: html

<a href="https://www.docker.com" target="_blank">Docker Desktop</a>

2. Для работы с системой контроля версий – |link_git|

.. |link_git| raw:: html

<a href="https://github.com/git-guides/install-git" target="_blank">Git</a>

3. IDE для работы с исходным кодом – |link_pycharm|

.. |link_pycharm| raw:: html

<a href="https://www.jetbrains.com/ru-ru/pycharm/download" target="_blank">PyCharm</a>


Установка
=========

1. Клонируйте репозиторий проекта в свою рабочую директорию:

.. code-block:: console

git clone https://github.com/MNV/python-course-graphql-gateway-example.git

Перед началом использования приложения необходимо его сконфигурировать.

.. note::

Для конфигурации выполните команды, описанные ниже, находясь в корневой директории проекта (на уровне с директорией `src`).

2. Скопируйте файл настроек `.env.sample`, создав файл `.env`:
.. code-block:: console

cp .env.sample .env

Этот файл содержит преднастроенные переменные окружения, значения которых будут общими для всего приложения.
Файл примера (`.env.sample`) содержит набор переменных со значениями по умолчанию.
Созданный файл `.env` можно настроить в зависимости от окружения.

.. warning::

Никогда не добавляйте в систему контроля версий заполненный файл `.env` для предотвращения компрометации информации о конфигурации приложения.

3. Соберите Docker-контейнер с помощью Docker Compose:
.. code-block:: console

docker compose build

Данную команду необходимо выполнять повторно в случае обновления зависимостей в файле `requirements.txt`.

4. После сборки контейнеров можно их запустить командой:
.. code-block:: console

docker compose up

Данная команда запустит собранные контейнеры для приложения и базы данных.
Когда запуск завершится, сервер начнет работать по адресу `http://127.0.0.1:8000`.



Использование
=============


Запросы
-------
Этот проект предоставляет фикстуры для тестирования GraphQL. Фикстуры расположены в `src/fixtures`.
В них содержатся JSON-файлы для информации о любимых местах и странах.
GraphQL-приложение использует эти фикстуры для эмуляции ответов REST API.

Пример запроса на получение списка любимых мест:

.. code-block:: graphql

query {
places {
latitude
longitude
description
city
locality
}
}

Пример запроса на получение списка любимых мест с информацией о странах:

.. code-block:: graphql

query {
places {
latitude
longitude
description
city
locality
country {
name
capital
alpha2code
alpha3code
capital
region
subregion
population
latitude
longitude
demonym
area
numericCode
flag
currencies
languages
}
}
}

Этот запрос запросит дополнительную информацию о связанных странах оптимальным способом, используя загрузчики данных, чтобы предотвратить проблему N + 1 запросов.

Автоматизация
=============

Проект содержит специальный файл (`Makefile`) для автоматизации выполнения команд:

1. Сборка Docker-контейнера.
2. Генерация документации.
3. Запуск форматирования кода.
4. Запуск статического анализа кода (выявление ошибок типов и форматирования кода).
5. Запуск автоматических тестов.
6. Запуск всех функций поддержки качества кода (форматирование, линтеры, автотесты).

Инструкция по запуску этих команд находится в файле `README.md`.


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


Для запуска автоматических тестов выполните команду:

.. code-block:: console

make test

Отчет о тестировании находится в файле `src/htmlcov/index.html`.


Документация к исходному коду
=============================

Сервисный слой
==============

Сервис для стран
----------------
.. automodule:: services.countries
:members:

Сервис для новостей
-------------------
.. automodule:: services.news
:members:

Сервис для мест
---------------
.. automodule:: services.places
:members:

Модели
======

Миксин
------
.. automodule:: models.mixins
:members:

Модель для стран
----------------
.. automodule:: models.countries
:members:

Модель для новостей
-------------------
.. automodule:: models.news
:members:

Модель для мест
---------------
.. automodule:: models.places
:members:
8 changes: 6 additions & 2 deletions src/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from promise.dataloader import DataLoader

from dataloaders import CountryLoader
from dataloaders import CountryLoader, NewsLoader

DATA_LOADER_COUNTRIES = "countries"
DATA_LOADER_NEWS = "news"


def register_dataloaders() -> Dict[str, DataLoader]:
Expand All @@ -14,7 +15,10 @@ def register_dataloaders() -> Dict[str, DataLoader]:
:return:
"""

return {DATA_LOADER_COUNTRIES: CountryLoader()}
return {
DATA_LOADER_COUNTRIES: CountryLoader(),
DATA_LOADER_NEWS: NewsLoader(),
}


def get_context() -> Dict[str, Dict[str, DataLoader]]:
Expand Down
21 changes: 21 additions & 0 deletions src/dataloaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from promise.dataloader import DataLoader

from services.countries import CountriesService
from services.news import NewsService


class CountryLoader(DataLoader):
Expand All @@ -24,3 +25,23 @@ def batch_load_fn( # pylint: disable=method-hidden

# формирование результата с сохранением порядка из alpha2codes
return Promise.resolve([countries_map.get(code) for code in alpha2codes])


class NewsLoader(DataLoader):
"""
Загрузчик данных о новостях.
"""

def batch_load_fn( # pylint: disable=method-hidden
self, alpha2codes: list[str]
) -> Promise:
"""
Функция для загрузки связанных данных по переданному множеству значений.
:param alpha2codes: Список ISO Alpha2-кодов стран
:return:
"""

news = NewsService().get_news()

# формирование результата с сохранением порядка из alpha2codes
return Promise.resolve([news.get(code.lower()) for code in alpha2codes if code])
45 changes: 45 additions & 0 deletions src/fixtures/news/ie.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"status": "ok",
"totalResults": 38,
"articles": [
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "RTE.ie",
"title": "Sunak tells Stormont leaders 'real work starts now' - RTE.ie",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiM2h0dHBzOi8vd3d3LnJ0ZS5pZS9uZXdzLzIwMjQvMDIwNS8xNDMwNTM4LXN0b3Jtb250L9IBH2h0dHBzOi8vYW1wLnJ0ZS5pZS9hbXAvMTQzMDUzOC8?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T14:17:58Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "The Guardian",
"title": "Cern aims to build \u20ac20bn atom-smasher to unlock secrets of universe - The Guardian",
"description": null,
"url": "https://news.google.com/rss/articles/CBMib2h0dHBzOi8vd3d3LnRoZWd1YXJkaWFuLmNvbS9zY2llbmNlLzIwMjQvZmViLzA1L2Nlcm4tYXRvbS1zbWFzaGVyLXVubG9jay1zZWNyZXRzLXVuaXZlcnNlLWxhcmdlLWhhZHJvbi1jb2xsaWRlctIBb2h0dHBzOi8vYW1wLnRoZWd1YXJkaWFuLmNvbS9zY2llbmNlLzIwMjQvZmViLzA1L2Nlcm4tYXRvbS1zbWFzaGVyLXVubG9jay1zZWNyZXRzLXVuaXZlcnNlLWxhcmdlLWhhZHJvbi1jb2xsaWRlcg?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T13:42:00Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "RTE.ie",
"title": "Dad's Army star Ian Lavender has died at the age of 77 - RTE.ie",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiaWh0dHBzOi8vd3d3LnJ0ZS5pZS9lbnRlcnRhaW5tZW50LzIwMjQvMDIwNS8xNDMwNTY2LWRhZHMtYXJteS1zdGFyLWlhbi1sYXZlbmRlci1oYXMtZGllZC1hdC10aGUtYWdlLW9mLTc3L9IBAA?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T13:18:45Z",
"content": null
}
]
}
45 changes: 45 additions & 0 deletions src/fixtures/news/rs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"status": "ok",
"totalResults": 34,
"articles": [
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "Espreso",
"title": "AKO IMATE OVE PROMENE NA KO\u017dI ODMAH SE JAVITE LEKARU: Obi\u010dno se javljaju kod ljudi STARIJIH OD 50 GODINA - Espreso",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiaWh0dHBzOi8vd3d3LmVzcHJlc28uY28ucnMvbGlmZXN0eWxlL3pkcmF2bGplLzE0MjU1MzAvYWtvLWltYXRlLW92ZS1wcm9tZW5lLW5hLWtvemktb2RtYWgtc2UtamF2aXRlLWxla2FyddIBWmh0dHBzOi8vd3d3LmVzcHJlc28uY28ucnMvYW1wLzE0MjU1MzAvYWtvLWltYXRlLW92ZS1wcm9tZW5lLW5hLWtvemktb2RtYWgtc2UtamF2aXRlLWxla2FydQ?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T14:22:12Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "Benchmark",
"title": "Apple savitljivi telefon mo\u017eda vidimo izme\u0111u 2026. i 2027. godine - Benchmark",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiY2h0dHBzOi8vYmVuY2htYXJrLnJzL3Zlc3RpL3VyZWRhamkvYXBwbGUtc2F2aXRsaml2aS10ZWxlZm9uLW1vemRhLXZpZGltby1pem1lZHUtMjAyNi1pLTIwMjctZ29kaW5lL9IBAA?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T14:11:45Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "Blic.rs",
"title": "\"BLIC\" SAZNAJE: HBO \u0107e Bikovi\u0107u isplatiti ceo honorar za \"White Lotus\", ODU\u0160EVI\u0106E VAS kada budete saznali kome glumac daje ceo iznos - Blic.rs",
"description": null,
"url": "https://news.google.com/rss/articles/CBMidmh0dHBzOi8vd3d3LmJsaWMucnMvemFiYXZhL2hiby1jZS1iaWtvdmljdS1pc3BsYXRpdGktY2VvLWhvbm9yYXItemEtd2hpdGUtbG90dXMtZXZvLWtvbWUtZ2x1bWFjLWRhamUtY2Vsb2t1cGFuL2NnNjl3ejnSAQA?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T14:08:44Z",
"content": null
}
]
}
45 changes: 45 additions & 0 deletions src/fixtures/news/ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"status": "ok",
"totalResults": 34,
"articles": [
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "\u0424\u043e\u043d\u0442\u0430\u043d\u043a\u0430.\u0420\u0443",
"title": "\u0417\u0430\u0432\u043e\u0434 \u00ab\u0410\u0432\u0442\u043e\u0442\u043e\u0440\u00bb \u0432 \u041a\u0430\u043b\u0438\u043d\u0438\u043d\u0433\u0440\u0430\u0434\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u043b \u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0431\u0440\u0435\u043d\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u043e\u0431\u0438\u043b\u0435\u0439 - 5 \u0444\u0435\u0432\u0440\u0430\u043b\u044f 2024 - \u0424\u043e\u043d\u0442\u0430\u043d\u043a\u0430.\u0420\u0443",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiLGh0dHBzOi8vd3d3LmZvbnRhbmthLnJ1LzIwMjQvMDIvMDUvNzMxOTc0NDMv0gEA?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T13:21:21Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "Meduza",
"title": "Politico: 13-\u0439 \u043f\u0430\u043a\u0435\u0442 \u0441\u0430\u043d\u043a\u0446\u0438\u0439 \u0415\u0421 \u043f\u0440\u043e\u0442\u0438\u0432 \u0420\u043e\u0441\u0441\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0441\u0438\u0442\u044c \u00ab\u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439\u00bb \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440 \u2014 Meduza - Meduza",
"description": null,
"url": "https://news.google.com/rss/articles/CBMic2h0dHBzOi8vbWVkdXphLmlvL25ld3MvMjAyNC8wMi8wNS9wb2xpdGljby0xMy15LXBha2V0LXNhbmt0c2l5LWVzLXByb3Rpdi1yb3NzaWktYnVkZXQtbm9zaXQtc2ltdm9saWNoZXNraXktaGFyYWt0ZXLSAQA?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T12:26:00Z",
"content": null
},
{
"source": {
"id": "google-news",
"name": "Google News"
},
"author": "\u0420\u0411\u041a-\u0423\u043a\u0440\u0430\u0438\u043d\u0430",
"title": "\u041d\u0435\u043c\u0435\u0446\u043a\u0438\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u043b \u0443\u0432\u0435\u0440\u0435\u043d \u0432 \u043f\u043e\u0431\u0435\u0434\u0435 \u0423\u043a\u0440\u0430\u0438\u043d\u044b \u0432 \u0432\u043e\u0439\u043d\u0435 \u0441 \u0420\u043e\u0441\u0441\u0438\u0435\u0439: \u0447\u0442\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e - \u0420\u0411\u041a-\u0423\u043a\u0440\u0430\u0438\u043d\u0430",
"description": null,
"url": "https://news.google.com/rss/articles/CBMiWWh0dHBzOi8vd3d3LnJiYy51YS91a3IvbmV3cy9uaW1ldHNraXktZ2VuZXJhbC11cGV2bmVuaXktcGVyZW1vemktdWtyYXlpbmktMTcwNzEzNTQ2OC5odG1s0gFdaHR0cHM6Ly93d3cucmJjLnVhL3Vrci9uZXdzL25pbWV0c2tpeS1nZW5lcmFsLXVwZXZuZW5peS1wZXJlbW96aS11a3JheWluaS0xNzA3MTM1NDY4Lmh0bWwvYW1w?oc=5",
"urlToImage": null,
"publishedAt": "2024-02-05T12:17:48Z",
"content": null
}
]
}
Loading