{"id":17361241,"url":"https://github.com/niqzart/ffs-test-task","last_synced_at":"2025-08-02T11:31:13.188Z","repository":{"id":115916171,"uuid":"525149602","full_name":"niqzart/ffs-test-task","owner":"niqzart","description":null,"archived":false,"fork":false,"pushed_at":"2023-12-03T15:53:14.000Z","size":157,"stargazers_count":0,"open_issues_count":0,"forks_count":21,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-16T22:22:23.438Z","etag":null,"topics":["flask","pytest","socketio","sqlalchemy","test-task"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/niqzart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-08-15T21:53:19.000Z","updated_at":"2023-10-05T12:43:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"e53c321d-333d-400d-9994-6699a7e306e2","html_url":"https://github.com/niqzart/ffs-test-task","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niqzart%2Fffs-test-task","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niqzart%2Fffs-test-task/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niqzart%2Fffs-test-task/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niqzart%2Fffs-test-task/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/niqzart","download_url":"https://codeload.github.com/niqzart/ffs-test-task/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228468860,"owners_count":17924939,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","pytest","socketio","sqlalchemy","test-task"],"created_at":"2024-10-15T19:31:59.410Z","updated_at":"2024-12-06T12:40:30.563Z","avatar_url":"https://github.com/niqzart.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Тестовое задание\n- [Описание](#Описание)\n- [Задание](#Задание)\n- [Рекомендации](#Рекомендации)\n- [Ссылки](#Ссылки)\n\n## Описание\nРепозиторий-заготовка для выполнения тестового задания для вступления в команду бэкенда. Призван погрузить в стек проекта, познакомить с используемыми библиотеками, в том числе внутрипроектными.\n\n### Стек\n- Язык программирования: [Python](https://www.python.org/downloads/) 3.11+\n- ORM-система: [SQLAlchemy](https://www.sqlalchemy.org/) 2.0+\n- Микро-фреймворк: [Flask](https://flask.palletsprojects.com/en/2.2.x/) 2.0+\n- ORM-Плагин: [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/) 3.0+\n- При участии: [Flask-RESTX](https://flask-restx.readthedocs.io/en/latest/index.html)\n- Не забывая о: [Pydantic-Marshals](https://github.com/niqzart/pydantic-marshals)\n- А также: [Flask-Fullstack](https://github.com/niqzart/flask-fullstack) 0.5.10\n\n### Начало и установка\n1. Создать публичный fork репозитория\n2. Склонировать репозиторий себе\n3. Создать виртуальное окружение **на python 3.11**\n4. Установить зависимости:\n```sh\npip install poetry==1.5.1\npoetry install\n```\n5. Запусить файл `app.py`, можно создать Run Configuration на его запуск\n6. Проверить, документация работает: [http://localhost:5000/doc/](http://localhost:5000/doc/)\n\n### Про тесты\n- В проекте настроены тесты на [pytest](https://docs.pytest.org/en/7.3.x/) для удобства тестирования SIO-интерфейсов\n- Все тесты лежат в папке `tests`\n- Предопределённые фикстуры:\n  - `client`: тестовый flask-клиент (модифицирован в ffs)\n  - `socketio_client`: тестовый socketio-клиент, созданный от `client`\n- Базовые тесты проверяют документацию, ошибки и авторизацию\n- Запуск командой: `pytest tests`\n\n## Задание\nСамо задание будет кастомизированно для каждого!\n\n## Рекомендации\n### Pydantic-Marshals\nБиблиотека для автоматического создания частичных pydantic-моделей. В проекте используется для:\n- Создания валидаторов из SQLAlchemy-маппингов ([пример в readme](https://github.com/niqzart/pydantic-marshals#sqlalchemy-basic-usage))\n- Тестирования json-ответов приложения ([документация](https://github.com/niqzart/pydantic-marshals/blob/main/docs/assert-contains.md))\n\n### Flask-Fullstack\nВ проекте во всю мощь используется библиотека flask-fullstack (FFS). В ней есть частичная документация, но вот пример использования вытащить из проекта не удалось. Стоит прочитать документацию в файлах:\n- [Интерфейсы для БД](https://github.com/niqzart/flask-fullstack/blob/d54696b1b982015eb64790174d42bd21f7811a46/flask_fullstack/base/interfaces.py)\n- [.database_searcher](https://github.com/niqzart/flask-fullstack/blob/d54696b1b982015eb64790174d42bd21f7811a46/flask_fullstack/base/mixins.py#L48)\n- [.jwt_authorizer](https://github.com/niqzart/flask-fullstack/blob/d54696b1b982015eb64790174d42bd21f7811a46/flask_fullstack/base/mixins.py#L96)\n- [ResourceController + его методы](https://github.com/niqzart/flask-fullstack/blob/d54696b1b982015eb64790174d42bd21f7811a46/flask_fullstack/restx/controller.py)\n\nНикто не запрещает читать код репозитория внутри проекта, где используется эта библиотека: [xi.backend](https://github.com/xi-effect/xi.backend)\n\nЗнание flask-restx и sqlalchemy сильно поможет в понимании ffs, уже с этими знаниями можно почитать информационный материал ниже:\n\n\u003cdetails\u003e\n  \u003csummary\u003eFFS: Порядок декораторов\u003c/summary\u003e\n\n  Все упаковщики запросов (`.a_response`, `.marshal_with`, `.marshal_list_with` или `.lister`) должны быть последним декоратором перед методами в `Resource`. Иначе вылет ошибки из других декораторов (`.argument_parser`, `.database_searcher`, `.jwt_authorizer`) будет либо подавлен, либо завёрнут в дополнительный слой ненужной вложенности, нарушая описанное в документации. Технически не относится к декораторам документирования, но ради лучшей читабельности и общности стоит везде складывать декораторы в одинаковом порядке.\n\n  - все декораторы документации параметров запроса\n  - все декораторы документации формата ответов\n  - декоратор авторизации (`.jwt_authorizer`)\n  - декоратор парсинга аргументов (`.argument_parser`)\n  - декоратор(-ы) поиска объектов в бд (`.database_searcher`)\n  - декоратор пост-обработки ответа (`.a_response`, `.marshal_with`, `.marshal_list_with` или `.lister`)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eFFS: Shortcut-ы для БД\u003c/summary\u003e\n\n  К объекту `db.session` добавлено несколько методов, упрощающих работу с логикой БД. По сути это простые shortcut-ы. Все их можно увидеть [тут](https://github.com/niqzart/flask-fullstack/blob/93d3c6696c33171315c078ab88c68ca7f7094361/flask_fullstack/utils/sqlalchemy.py#L21)\n\n  Ко всем классам, наследующим `Base` (именно `Base` из `common`, не `db.Model`!) теперь добавляется набор полезных методов, которые могут значительно уменьшить объём работы. Они создаются и документированы [тут](https://github.com/niqzart/ffs-test-task/blob/main/common/config.py#L67)\n\n\u003c/details\u003e\n\n[FFS: SocketIO (частичная дока внутри проекта)](https://github.com/xi-effect/xieffect-backend/pull/110)\n\n### Стиль кода\n- **Будет проверяться**\n- Соблюдение PEP8 обязательно\n- Желательно не забывать Zen\n- DRY приветствуется\n- Автоматическое реформатирование рекомендуется\n- Стоит поглядывать на стиль других файлов проекта\n\n### Стиль git-а\n- Желательно соблюдать [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)\n- Решить задачу в несколько коммитов\n- Pull Request с мини-описанием приветствуется\n\n## Ссылки\n### Общее\n- [PEP8](https://www.python.org/dev/peps/pep-0008/)\n- [pytest](https://docs.pytest.org/en/6.2.x/contents.html)\n\n### Flask и расширения:\n- [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/)\n- [Flask-JWT-Extened](https://flask-jwt-extended.readthedocs.io/en/stable/)\n- [Flask-RESTX](https://flask-restx.readthedocs.io/en/latest/index.html)\n- [Flask Testing](https://flask.palletsprojects.com/en/2.0.x/testing/)\n\n### SQLAlchemy:\n- [Полный туториал](https://docs.sqlalchemy.org/en/20/tutorial/index.html)\n- [Построение табличек](https://docs.sqlalchemy.org/en/20/tutorial/metadata.html#tutorial-orm-table-metadata)\n- [ORM Relationships](https://docs.sqlalchemy.org/en/20/tutorial/orm_related_objects.html)\n- [Insert-Update-Delete в ORM](https://docs.sqlalchemy.org/en/20/tutorial/orm_data_manipulation.html)\n- [Select в ORM](https://docs.sqlalchemy.org/en/20/orm/queryguide/select.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniqzart%2Fffs-test-task","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fniqzart%2Fffs-test-task","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniqzart%2Fffs-test-task/lists"}