diff --git a/backend/endpoints/__init__.py b/backend/endpoints/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/endpoints/scan.py b/backend/endpoints/scan.py index aa8e6f9da..1c96796f1 100644 --- a/backend/endpoints/scan.py +++ b/backend/endpoints/scan.py @@ -1,5 +1,8 @@ import json import emoji +import socketio +from rq import Queue +from redis import Redis from logger.logger import log from utils import fs, fastapi @@ -7,14 +10,19 @@ from utils.exceptions import PlatformsNotFoundException, RomsNotFoundException from handler import dbh from models.platform import Platform from models.rom import Rom -from handler.socket_manager import SocketManager +from handler.socket_manager import socket_server -async def scan( - sm: SocketManager, _sid: str, platforms: str, complete_rescan: bool = True -): +redis_conn = Redis() +scan_queue = Queue(connection=redis_conn) + + +async def scan_filesystem(platforms: str, complete_rescan: bool = True): """Scan platforms and roms and write them in database.""" + # Connect to external socketio server + sm = socketio.AsyncRedisManager("redis://", write_only=True) + log.info(emoji.emojize(":magnifying_glass_tilted_right: Scanning ")) fs.store_default_resources() @@ -39,7 +47,6 @@ async def scan( await sm.emit( "scan:scanning_platform", {"p_name": scanned_platform.name, "p_slug": scanned_platform.slug}, - ignore_queue=True, ) dbh.add_platform(scanned_platform) @@ -56,10 +63,10 @@ async def scan( "scan:scanning_rom", { "p_slug": scanned_platform.slug, + "p_name": scanned_platform.name, "file_name": scanned_rom.file_name, "r_name": scanned_rom.r_name, }, - ignore_queue=True, ) if rom_id: @@ -69,4 +76,9 @@ async def scan( dbh.purge_roms(scanned_platform.slug, [rom["file_name"] for rom in fs_roms]) dbh.purge_platforms(fs_platforms) - await sm.emit("scan:done") + await sm.emit("scan:done", {}) + + +@socket_server.on("scan") +def scan_handler(_sid: str, platforms: str, complete_rescan: bool = True): + scan_queue.enqueue(scan_filesystem, platforms, complete_rescan) diff --git a/backend/handler/socket_manager.py b/backend/handler/socket_manager.py index cf1bcdbaa..71d2193d8 100644 --- a/backend/handler/socket_manager.py +++ b/backend/handler/socket_manager.py @@ -1,32 +1,12 @@ import socketio -class SocketManager(object): - def __new__(cls): - if not hasattr(cls, "instance"): - cls.instance = super(SocketManager, cls).__new__(cls) - return cls.instance +socket_server = socketio.AsyncServer( + cors_allowed_origins="*", + async_mode="asgi", + logger=False, + engineio_logger=False, + client_manager=socketio.AsyncRedisManager("redis://"), +) - def __init__(self): - self.server = socketio.AsyncServer( - cors_allowed_origins="*", - async_mode="asgi", - logger=False, - engineio_logger=False, - ) - self.app = socketio.ASGIApp(self.server) - - @property - def on(self): - return self.server.on - - @property - def send(self): - return self.server.send - - @property - def emit(self): - return self.server.emit - - def mount_to(self, path: str, app): - app.mount(path, self.app) +socket_app = socketio.ASGIApp(socket_server) diff --git a/backend/main.py b/backend/main.py index 94b506780..e1fe9818a 100644 --- a/backend/main.py +++ b/backend/main.py @@ -5,8 +5,8 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi_pagination import add_pagination from config import DEV_PORT, DEV_HOST -from handler.socket_manager import SocketManager -from endpoints import scan, search, platform, rom +from handler.socket_manager import socket_app +from endpoints import search, platform, rom, scan # noqa app = FastAPI() app.add_middleware( @@ -21,20 +21,7 @@ app.include_router(platform.router) app.include_router(rom.router) add_pagination(app) - -sm = SocketManager() -sm.mount_to("/ws", app) - - -async def scan_handler(*args): - try: - await scan.scan(sm, *args) - except Exception as err: - await sm.emit("scan:done_ko", str(err)) - raise (err) - - -sm.on("scan", handler=scan_handler) +app.mount("/ws", socket_app) @app.on_event("startup") diff --git a/docker-compose.yml b/docker-compose.yml index f17c8b0c1..077af13c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: mariadb: image: mariadb:latest container_name: mariadb + restart: unless-stopped environment: - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWD} - MYSQL_DATABASE=${DB_NAME} @@ -10,4 +11,10 @@ services: - MYSQL_PASSWORD=${DB_PASSWD} ports: - ${DB_PORT}:3306 - restart: "no" + + redis: + image: redis:alpine + container_name: redis + restart: unless-stopped + ports: + - ${REDIS_PORT}:6379 diff --git a/env.template b/env.template index 17e16876a..b30c8ae02 100644 --- a/env.template +++ b/env.template @@ -18,3 +18,6 @@ DB_NAME=romm DB_USER=romm DB_PASSWD= DB_ROOT_PASSWD= + +# Redis config (development only) +REDIS_PORT=6379 diff --git a/frontend/src/views/library/Scan.vue b/frontend/src/views/library/Scan.vue index 5b15fbcf9..18e0d85da 100644 --- a/frontend/src/views/library/Scan.vue +++ b/frontend/src/views/library/Scan.vue @@ -23,12 +23,21 @@ socket.on("scan:scanning_platform", ({ p_name, p_slug }) => { }); }); -socket.on("scan:scanning_rom", ({ p_slug, file_name, r_name }) => { - const platform = scannedPlatforms.value.find((p) => p.slug === p_slug); - platform.roms.push({ - name: r_name, - file_name: file_name, - }); +socket.on("scan:scanning_rom", ({ p_slug, p_name, ...rom }) => { + let platform = scannedPlatforms.value.find((p) => p.slug === p_slug); + + // Add the platform if the socket dropped and it's missing + if (!platform) { + scannedPlatforms.value.push({ + name: p_name, + slug: p_slug, + roms: [], + }); + + platform = scannedPlatforms.slice(-1); + } + + platform.roms.push(rom); }); socket.on("scan:done", () => { @@ -52,6 +61,8 @@ socket.on("scan:done_ko", (msg) => { socket.disconnect(); }); +window.socket = socket; + // Functions async function scan() { scanning.set(true); @@ -135,8 +146,8 @@ async function scan() { {{ platform.name }} - - • Identified {{ rom.name }} 👾 + + • Identified {{ rom.r_name }} 👾 • {{ rom.file_name }} not found in IGDB diff --git a/poetry.lock b/poetry.lock index 9f34e424c..6517df6de 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,27 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "aioredis" +version = "2.0.1" +description = "asyncio (PEP 3156) Redis support" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aioredis-2.0.1-py3-none-any.whl", hash = "sha256:9ac0d0b3b485d293b8ca1987e6de8658d7dafcca1cddfcd1d506cae8cdebfdd6"}, + {file = "aioredis-2.0.1.tar.gz", hash = "sha256:eaa51aaf993f2d71f54b70527c440437ba65340588afeb786cd87c55c89cd98e"}, +] + +[package.dependencies] +async-timeout = "*" +typing-extensions = "*" + +[package.extras] +hiredis = ["hiredis (>=1.0)"] [[package]] name = "alembic" version = "1.10.4" description = "A database migration tool for SQLAlchemy." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -24,7 +41,6 @@ tz = ["python-dateutil"] name = "anyio" version = "3.6.2" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -45,7 +61,6 @@ trio = ["trio (>=0.16,<0.22)"] name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "main" optional = false python-versions = "*" files = [ @@ -57,7 +72,6 @@ files = [ name = "asttokens" version = "2.2.1" description = "Annotate AST trees with source code positions" -category = "main" optional = false python-versions = "*" files = [ @@ -71,11 +85,21 @@ six = "*" [package.extras] test = ["astroid", "pytest"] +[[package]] +name = "async-timeout" +version = "4.0.2" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.6" +files = [ + {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, + {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, +] + [[package]] name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "main" optional = false python-versions = "*" files = [ @@ -87,7 +111,6 @@ files = [ name = "bidict" version = "0.22.1" description = "The bidirectional mapping library for Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -104,7 +127,6 @@ test = ["hypothesis", "pytest", "pytest-benchmark[histogram]", "pytest-cov", "py name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -116,7 +138,6 @@ files = [ name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -201,7 +222,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -216,7 +236,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -228,7 +247,6 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -240,7 +258,6 @@ files = [ name = "emoji" version = "2.2.0" description = "Emoji for Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -254,7 +271,6 @@ dev = ["coverage", "coveralls", "pytest"] name = "exceptiongroup" version = "1.1.2" description = "Backport of PEP 654 (exception groups)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -269,7 +285,6 @@ test = ["pytest (>=6)"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" -category = "main" optional = false python-versions = "*" files = [ @@ -284,7 +299,6 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "fastapi" version = "0.95.1" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -306,7 +320,6 @@ test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6 name = "fastapi-pagination" version = "0.12.4" description = "FastAPI pagination" -category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -339,7 +352,6 @@ tortoise = ["tortoise-orm (>=0.16.18,<0.20.0)"] name = "greenlet" version = "2.0.2" description = "Lightweight in-process concurrent programming" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -413,7 +425,6 @@ test = ["objgraph", "psutil"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -425,7 +436,6 @@ files = [ name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -437,7 +447,6 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -449,7 +458,6 @@ files = [ name = "ipdb" version = "0.13.13" description = "IPython-enabled pdb" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -466,7 +474,6 @@ tomli = {version = "*", markers = "python_version > \"3.6\" and python_version < name = "ipython" version = "8.13.2" description = "IPython: Productive Interactive Computing" -category = "main" optional = false python-versions = ">=3.9" files = [ @@ -505,7 +512,6 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -525,7 +531,6 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -545,7 +550,6 @@ testing = ["pytest"] name = "mariadb" version = "1.1.7" description = "Python MariaDB extension" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -567,7 +571,6 @@ packaging = "*" name = "markupsafe" version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -627,7 +630,6 @@ files = [ name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -642,7 +644,6 @@ traitlets = "*" name = "multidict" version = "6.0.4" description = "multidict implementation" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -726,7 +727,6 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -738,7 +738,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -754,7 +753,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "main" optional = false python-versions = "*" files = [ @@ -769,7 +767,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "main" optional = false python-versions = "*" files = [ @@ -781,7 +778,6 @@ files = [ name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -797,7 +793,6 @@ testing = ["pytest", "pytest-benchmark"] name = "prompt-toolkit" version = "3.0.38" description = "Library for building powerful interactive command lines in Python" -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -812,7 +807,6 @@ wcwidth = "*" name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -824,7 +818,6 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -category = "main" optional = false python-versions = "*" files = [ @@ -839,7 +832,6 @@ tests = ["pytest"] name = "pydantic" version = "1.10.7" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -892,7 +884,6 @@ email = ["email-validator (>=1.0.3)"] name = "pydash" version = "7.0.6" description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -910,7 +901,6 @@ dev = ["Sphinx", "black", "build", "coverage", "docformatter", "flake8", "flake8 name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -925,7 +915,6 @@ plugins = ["importlib-metadata"] name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -948,7 +937,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-env" version = "0.8.2" description = "py.test plugin that allows you to add environment variables." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -966,7 +954,6 @@ test = ["coverage (>=7.2.7)", "pytest-mock (>=3.10)"] name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -984,7 +971,6 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "pytest-vcr" version = "1.0.2" description = "Plugin for managing VCR.py cassettes" -category = "main" optional = false python-versions = "*" files = [ @@ -1000,7 +986,6 @@ vcrpy = "*" name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1015,7 +1000,6 @@ six = ">=1.5" name = "python-dotenv" version = "1.0.0" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1030,7 +1014,6 @@ cli = ["click (>=5.0)"] name = "python-engineio" version = "4.4.1" description = "Engine.IO server and client for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1046,7 +1029,6 @@ client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] name = "python-socketio" version = "5.8.0" description = "Socket.IO server and client for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1066,7 +1048,6 @@ client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1112,11 +1093,28 @@ files = [ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] +[[package]] +name = "redis" +version = "4.6.0" +description = "Python client for Redis database and key-value store" +optional = false +python-versions = ">=3.7" +files = [ + {file = "redis-4.6.0-py3-none-any.whl", hash = "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c"}, + {file = "redis-4.6.0.tar.gz", hash = "sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} + +[package.extras] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + [[package]] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1134,11 +1132,25 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rq" +version = "1.15.1" +description = "RQ is a simple, lightweight, library for creating background jobs, and processing them." +optional = false +python-versions = ">=3.6" +files = [ + {file = "rq-1.15.1-py2.py3-none-any.whl", hash = "sha256:6e243d8d9c4af4686ded4b01b25ea1ff4bac4fc260b02638fbe9c8c17b004bd1"}, + {file = "rq-1.15.1.tar.gz", hash = "sha256:1f49f4ac1a084044bb8e95b3f305c0bf17e55618b08c18e0b60c080f12d6f008"}, +] + +[package.dependencies] +click = ">=5.0.0" +redis = ">=4.0.0" + [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1150,7 +1162,6 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1162,7 +1173,6 @@ files = [ name = "sqlakeyset" version = "2.0.1684285512" description = "offset-free paging for sqlalchemy" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -1180,7 +1190,6 @@ typing_extensions = ">=4,<5" name = "sqlalchemy" version = "2.0.12" description = "Database Abstraction Library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1228,7 +1237,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} typing-extensions = ">=4.2.0" [package.extras] @@ -1258,7 +1267,6 @@ sqlcipher = ["sqlcipher3-binary"] name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" -category = "main" optional = false python-versions = "*" files = [ @@ -1278,7 +1286,6 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "starlette" version = "0.26.1" description = "The little ASGI library that shines." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1296,7 +1303,6 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyam name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1308,7 +1314,6 @@ files = [ name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1324,7 +1329,6 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "typing-extensions" version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1336,7 +1340,6 @@ files = [ name = "unidecode" version = "1.3.6" description = "ASCII transliterations of Unicode text" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1348,7 +1351,6 @@ files = [ name = "urllib3" version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1366,7 +1368,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "uvicorn" version = "0.22.0" description = "The lightning-fast ASGI server." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1385,7 +1386,6 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", name = "vcrpy" version = "5.1.0" description = "Automatically mock your HTTP interactions to simplify and speed up testing" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1402,7 +1402,6 @@ yarl = "*" name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -1414,7 +1413,6 @@ files = [ name = "websockets" version = "11.0.3" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1494,7 +1492,6 @@ files = [ name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -1579,7 +1576,6 @@ files = [ name = "yarl" version = "1.9.2" description = "Yet another URL library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1666,4 +1662,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "226d69976d98caf0de533c83cd447c2e1074234f104ecedc33eb3b61d50a58a9" +content-hash = "9f86d5d57b6df96b54973786c7129f7a6bb2182466558463a8336ffe0cc5c0f5" diff --git a/pyproject.toml b/pyproject.toml index eeea9bea0..9a8411e35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,8 @@ pytest-env = "^0.8.2" pytest-vcr = "^1.0.2" pytest-mock = "^3.11.1" mariadb = "1.1.7" +rq = "^1.15.1" +aioredis = "^2.0.1" [build-system]