alessandro trinca tornidor
commited on
Commit
·
d7027f5
1
Parent(s):
7024f75
ci: add docker and docker compose support
Browse files- .gitignore +4 -0
- Dockerfile +50 -0
- README.md +25 -0
- docker-compose.yaml +26 -0
- dockerfiles/dockerfile_my_ghost_writer_base +74 -0
- my_ghost_writer/app.py +17 -9
- my_ghost_writer/constants.py +9 -10
- my_ghost_writer/pymongo_utils.py +2 -2
- poetry.lock +152 -25
- pyproject.toml +3 -4
- requirements_poetry.txt +1 -0
- template.env +7 -7
- tests/test_app.py +1 -1
- tests/test_pymongo_utils.py +2 -2
.gitignore
CHANGED
|
@@ -283,3 +283,7 @@ fabric.properties
|
|
| 283 |
# node_modules
|
| 284 |
node_modules
|
| 285 |
*/node_modules/*/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
# node_modules
|
| 284 |
node_modules
|
| 285 |
*/node_modules/*/*
|
| 286 |
+
|
| 287 |
+
# mongodb
|
| 288 |
+
mongo/*
|
| 289 |
+
mongodb/*
|
Dockerfile
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM registry.gitlab.com/aletrn/my_ghost_writer_base:0.4.0
|
| 2 |
+
|
| 3 |
+
LABEL authors="trincadev"
|
| 4 |
+
|
| 5 |
+
# Include global arg in this stage of the build
|
| 6 |
+
ARG WORKDIR_ROOT="/var/task"
|
| 7 |
+
ENV VIRTUAL_ENV=${WORKDIR_ROOT}/.venv PATH="${WORKDIR_ROOT}/.venv/bin:$PATH"
|
| 8 |
+
ENV WRITE_TMP_ON_DISK=""
|
| 9 |
+
ENV MOUNT_GRADIO_APP=""
|
| 10 |
+
ENV VITE__STATIC_INDEX_URL="/static"
|
| 11 |
+
ENV VITE__INDEX_URL="/"
|
| 12 |
+
ENV HOME_USER=/home/python
|
| 13 |
+
|
| 14 |
+
# Set working directory to function root directory
|
| 15 |
+
WORKDIR ${WORKDIR_ROOT}
|
| 16 |
+
# workaround for missing /home folder
|
| 17 |
+
RUN ls -ld ${HOME_USER}
|
| 18 |
+
RUN ls -lA ${HOME_USER}
|
| 19 |
+
|
| 20 |
+
COPY --chown=python:python requirements_poetry.txt pyproject.toml poetry.lock README.md ${WORKDIR_ROOT}/
|
| 21 |
+
COPY --chown=python:python ./lite.koboldai.net ${WORKDIR_ROOT}/lite.koboldai.net
|
| 22 |
+
COPY --chown=python:python ./my_ghost_writer ${WORKDIR_ROOT}/my_ghost_writer
|
| 23 |
+
COPY --chown=python:python ./static ${WORKDIR_ROOT}/static
|
| 24 |
+
# RUN . ${WORKDIR_ROOT}/.venv && which python && echo "# install samgis #" && pip install .
|
| 25 |
+
RUN if [ "${WRITE_TMP_ON_DISK}" != "" ]; then mkdir {WRITE_TMP_ON_DISK}; fi
|
| 26 |
+
RUN if [ "${WRITE_TMP_ON_DISK}" != "" ]; then ls -l {WRITE_TMP_ON_DISK}; fi
|
| 27 |
+
|
| 28 |
+
RUN ls -l /usr/bin/which
|
| 29 |
+
RUN /usr/bin/which python
|
| 30 |
+
RUN python --version
|
| 31 |
+
RUN pip list
|
| 32 |
+
RUN echo "PATH: ${PATH}."
|
| 33 |
+
RUN echo "WORKDIR_ROOT: ${WORKDIR_ROOT}."
|
| 34 |
+
RUN ls -l ${WORKDIR_ROOT}
|
| 35 |
+
RUN ls -ld ${WORKDIR_ROOT}
|
| 36 |
+
RUN ls -l ${WORKDIR_ROOT}/
|
| 37 |
+
RUN python -c "import sys; print(sys.path)"
|
| 38 |
+
RUN python -c "import fastapi"
|
| 39 |
+
RUN python -c "import uvicorn"
|
| 40 |
+
RUN python -c "import pymongo"
|
| 41 |
+
RUN python -c "import requests"
|
| 42 |
+
RUN df -h
|
| 43 |
+
RUN ls -l ${WORKDIR_ROOT}/my_ghost_writer/app.py
|
| 44 |
+
RUN ls -l ${WORKDIR_ROOT}/lite.koboldai.net/index.html
|
| 45 |
+
|
| 46 |
+
USER 999
|
| 47 |
+
EXPOSE 7860
|
| 48 |
+
|
| 49 |
+
CMD ["uvicorn", "my_ghost_writer.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
| 50 |
+
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl -f http://localhost:7860/health
|
README.md
CHANGED
|
@@ -12,6 +12,7 @@ A simple helper for writers.
|
|
| 12 |
* Use NLP to stem words for more accurate results
|
| 13 |
* Support for uploading or typing in text
|
| 14 |
* User-friendly interface with a simple editor and display of word frequencies
|
|
|
|
| 15 |
|
| 16 |
## Technologies Used
|
| 17 |
|
|
@@ -44,7 +45,9 @@ If using the webserver with the module (`python -m ghost_writer.app.py`) it's ne
|
|
| 44 |
* `index.css`
|
| 45 |
* `API_MODE` to avoid mounting the static folder. This will define only the API endpoints
|
| 46 |
* `/health`
|
|
|
|
| 47 |
* `/words-frequency`
|
|
|
|
| 48 |
|
| 49 |
### Installation script
|
| 50 |
|
|
@@ -80,6 +83,28 @@ docker run --env=MONGO_MAJOR=8.0 \
|
|
| 80 |
-d mongo:8-noble
|
| 81 |
```
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
## Contributing
|
| 84 |
|
| 85 |
Pull requests are welcome! Please make sure to test your changes thoroughly before submitting a pull request.
|
|
|
|
| 12 |
* Use NLP to stem words for more accurate results
|
| 13 |
* Support for uploading or typing in text
|
| 14 |
* User-friendly interface with a simple editor and display of word frequencies
|
| 15 |
+
* WIP: thesaurus, powered by [wordsapi](https://www.wordsapi.com/) (you need to get your own wordsapi API key)
|
| 16 |
|
| 17 |
## Technologies Used
|
| 18 |
|
|
|
|
| 45 |
* `index.css`
|
| 46 |
* `API_MODE` to avoid mounting the static folder. This will define only the API endpoints
|
| 47 |
* `/health`
|
| 48 |
+
* `/health-mongo`
|
| 49 |
* `/words-frequency`
|
| 50 |
+
* `/thesaurus-wordsapi`
|
| 51 |
|
| 52 |
### Installation script
|
| 53 |
|
|
|
|
| 83 |
-d mongo:8-noble
|
| 84 |
```
|
| 85 |
|
| 86 |
+
## Docker
|
| 87 |
+
|
| 88 |
+
To build the project with docker:
|
| 89 |
+
|
| 90 |
+
```
|
| 91 |
+
DOCKER_VERSION=$(grep version pyproject.toml |head -1|cut -d'=' -f2|cut -d'"' -f2);
|
| 92 |
+
docker build . --progress=plain --tag registry.gitlab.com/aletrn/my_ghost_writer:${DOCKER_VERSION}
|
| 93 |
+
docker build . -f dockerfiles/dockerfile_my_ghost_writer_base --progress=plain --tag registry.gitlab.com/aletrn/my_ghost_writer_base:${DOCKER_VERSION}
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
To run the docker container (you still need to configure the mongodb endpoint to use the single my_ghost_writer container):
|
| 97 |
+
```
|
| 98 |
+
docker run -d --name my_ghost_writer -p 7860:7860 -e WORDSAPI_KEY=${WORDSAPI_KEY} -e ME_CONFIG_MONGODB_USE_OK=TRUE registry.gitlab.com/aletrn/my_ghost_writer:0.4.0; docker logs -f my_ghost_writer
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
To source more than one env variable, you can use this command:
|
| 102 |
+
```
|
| 103 |
+
set -o allexport && source <(cat ./.env) && set +o allexport;
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
Instead to simple
|
| 107 |
+
|
| 108 |
## Contributing
|
| 109 |
|
| 110 |
Pull requests are welcome! Please make sure to test your changes thoroughly before submitting a pull request.
|
docker-compose.yaml
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
my_ghost_writer:
|
| 3 |
+
env_file:
|
| 4 |
+
- ./.env
|
| 5 |
+
- ./.env_source
|
| 6 |
+
build:
|
| 7 |
+
context: .
|
| 8 |
+
tags:
|
| 9 |
+
- registry.gitlab.com/aletrn/my_ghost_writer:0.4.0
|
| 10 |
+
ports:
|
| 11 |
+
- "7860:7860"
|
| 12 |
+
environment:
|
| 13 |
+
ME_CONFIG_MONGODB_URL: mongodb://mongo:27017/
|
| 14 |
+
|
| 15 |
+
mongo:
|
| 16 |
+
environment:
|
| 17 |
+
- MONGO_MAJOR=8.0
|
| 18 |
+
- HOME=/data/db
|
| 19 |
+
image: "mongo:8-noble"
|
| 20 |
+
volumes:
|
| 21 |
+
- ./mongo:/data
|
| 22 |
+
- /data/configdb
|
| 23 |
+
- /data/db
|
| 24 |
+
ports:
|
| 25 |
+
- "27017:27017"
|
| 26 |
+
restart: always
|
dockerfiles/dockerfile_my_ghost_writer_base
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Include global ARGs at the dockerfile top
|
| 2 |
+
ARG ARCH="x86_64"
|
| 3 |
+
ARG WORKDIR_ROOT="/var/task"
|
| 4 |
+
ARG FASTAPI_STATIC="${WORKDIR_ROOT}/static"
|
| 5 |
+
ARG PYTHONPATH="${WORKDIR_ROOT}:${PYTHONPATH}:/usr/local/lib/python3/dist-packages"
|
| 6 |
+
ARG POETRY_NO_INTERACTION=1
|
| 7 |
+
ARG POETRY_VIRTUALENVS_IN_PROJECT=1
|
| 8 |
+
ARG POETRY_VIRTUALENVS_CREATE=1
|
| 9 |
+
ARG POETRY_CACHE_DIR=/tmp/poetry_cache
|
| 10 |
+
ARG HOME_USER=/home/python
|
| 11 |
+
|
| 12 |
+
FROM python:3.13-bookworm AS builder_global
|
| 13 |
+
LABEL authors="trincadev"
|
| 14 |
+
|
| 15 |
+
ARG ARCH
|
| 16 |
+
ARG WORKDIR_ROOT
|
| 17 |
+
ARG PYTHONPATH
|
| 18 |
+
ARG POETRY_NO_INTERACTION
|
| 19 |
+
ARG POETRY_VIRTUALENVS_IN_PROJECT
|
| 20 |
+
ARG POETRY_VIRTUALENVS_CREATE
|
| 21 |
+
ARG POETRY_CACHE_DIR
|
| 22 |
+
|
| 23 |
+
RUN echo "ARCH: $ARCH ..."
|
| 24 |
+
RUN echo "WORKDIR_ROOT: ${WORKDIR_ROOT} ..."
|
| 25 |
+
RUN echo "PYTHONPATH: ${PYTHONPATH} ..."
|
| 26 |
+
RUN echo "HOME_USER: ${HOME_USER} ..."
|
| 27 |
+
RUN echo "==========================="
|
| 28 |
+
|
| 29 |
+
RUN echo "ARG POETRY_CACHE_DIR: ${POETRY_CACHE_DIR} ..."
|
| 30 |
+
RUN echo "ARG PYTHONPATH: $PYTHONPATH ..."
|
| 31 |
+
RUN echo "arg dep:"
|
| 32 |
+
|
| 33 |
+
RUN ls -ld ${HOME_USER}
|
| 34 |
+
RUN ls -l ${HOME_USER}
|
| 35 |
+
RUN groupadd -g 999 python && useradd -r -u 999 -g python python
|
| 36 |
+
# Set working directory to function root directory
|
| 37 |
+
RUN mkdir ${WORKDIR_ROOT} && chown python:python ${WORKDIR_ROOT}
|
| 38 |
+
WORKDIR ${WORKDIR_ROOT}
|
| 39 |
+
COPY --chown=python:python requirements_poetry.txt pyproject.toml poetry.lock README.md ${WORKDIR_ROOT}/
|
| 40 |
+
COPY --chown=python:python ../lite.koboldai.net ${WORKDIR_ROOT}/lite.koboldai.net
|
| 41 |
+
COPY --chown=python:python ../my_ghost_writer ${WORKDIR_ROOT}/my_ghost_writer
|
| 42 |
+
|
| 43 |
+
# poetry installation path is NOT within ${WORKDIR_ROOT}: not needed for runtime docker image
|
| 44 |
+
RUN python -m pip install -r ${WORKDIR_ROOT}/requirements_poetry.txt
|
| 45 |
+
|
| 46 |
+
RUN which poetry && poetry --version && poetry config --list
|
| 47 |
+
RUN poetry config virtualenvs.path ${WORKDIR_ROOT}
|
| 48 |
+
RUN echo "# poetry config --list #" && poetry config --list
|
| 49 |
+
RUN poetry install --with webserver --no-cache
|
| 50 |
+
|
| 51 |
+
FROM python:3.13-slim-bookworm AS runtime
|
| 52 |
+
|
| 53 |
+
ARG ARCH
|
| 54 |
+
ARG WORKDIR_ROOT
|
| 55 |
+
ARG HOME_USER
|
| 56 |
+
|
| 57 |
+
ENV VIRTUAL_ENV=${WORKDIR_ROOT}/.venv PATH="${WORKDIR_ROOT}/.venv/bin:$PATH"
|
| 58 |
+
|
| 59 |
+
# workaround for missing /home folder
|
| 60 |
+
RUN mkdir -p /home
|
| 61 |
+
RUN groupadd -g 999 python && useradd -r -u 999 -g python python
|
| 62 |
+
RUN ls -l /home
|
| 63 |
+
RUN ls -ld /home
|
| 64 |
+
RUN mkdir -p ${HOME_USER} ${HOME_USER}/.config && chown python:python -R ${HOME_USER}
|
| 65 |
+
RUN ls -ld ${HOME_USER}
|
| 66 |
+
RUN ls -lA ${HOME_USER}
|
| 67 |
+
RUN mkdir ${WORKDIR_ROOT} && chown python:python ${WORKDIR_ROOT}
|
| 68 |
+
|
| 69 |
+
COPY --from=builder_global ${WORKDIR_ROOT}/.venv ${WORKDIR_ROOT}/.venv
|
| 70 |
+
RUN . ${WORKDIR_ROOT}/.venv && which python && pip list
|
| 71 |
+
|
| 72 |
+
RUN echo "new WORKDIR_ROOT after hidden venv copy => ${WORKDIR_ROOT}"
|
| 73 |
+
RUN ls -ld ${WORKDIR_ROOT}/
|
| 74 |
+
RUN ls -lA ${WORKDIR_ROOT}/
|
my_ghost_writer/app.py
CHANGED
|
@@ -4,7 +4,6 @@ import json
|
|
| 4 |
from datetime import datetime
|
| 5 |
|
| 6 |
import requests
|
| 7 |
-
import starlette.status
|
| 8 |
import uvicorn
|
| 9 |
from asgi_correlation_id import CorrelationIdMiddleware
|
| 10 |
from fastapi import FastAPI, Request
|
|
@@ -16,21 +15,22 @@ from pymongo import __version__ as pymongo_version
|
|
| 16 |
from pymongo.errors import PyMongoError
|
| 17 |
|
| 18 |
from my_ghost_writer import pymongo_operations_rw, exception_handlers
|
| 19 |
-
from my_ghost_writer.constants import (app_logger, ALLOWED_ORIGIN_LIST, API_MODE, DOMAIN, IS_TESTING,
|
| 20 |
-
|
|
|
|
| 21 |
from my_ghost_writer.pymongo_utils import mongodb_health_check
|
| 22 |
from my_ghost_writer.text_parsers import text_stemming
|
| 23 |
from my_ghost_writer.type_hints import RequestTextFrequencyBody, RequestQueryThesaurusWordsapiBody
|
| 24 |
|
| 25 |
|
| 26 |
async def mongo_health_check_background_task():
|
| 27 |
-
app_logger.info(f"starting task,
|
| 28 |
-
while
|
| 29 |
try:
|
| 30 |
db_ok["mongo_ok"] = health_mongo() == "Mongodb: still alive..."
|
| 31 |
except PyMongoError:
|
| 32 |
db_ok["mongo_ok"] = False
|
| 33 |
-
await asyncio.sleep(
|
| 34 |
|
| 35 |
|
| 36 |
async def lifespan(app: FastAPI):
|
|
@@ -52,7 +52,7 @@ app.add_middleware(
|
|
| 52 |
allow_credentials=True,
|
| 53 |
allow_methods=["GET", "POST"]
|
| 54 |
)
|
| 55 |
-
db_ok = {"mongo_ok":
|
| 56 |
|
| 57 |
|
| 58 |
@app.middleware("http")
|
|
@@ -75,7 +75,7 @@ def health():
|
|
| 75 |
@app.get("/health-mongo")
|
| 76 |
def health_mongo() -> str:
|
| 77 |
app_logger.info(f"pymongo driver version:{pymongo_version}!")
|
| 78 |
-
if
|
| 79 |
try:
|
| 80 |
db_ok["mongo_ok"] = mongodb_health_check()
|
| 81 |
return "Mongodb: still alive..."
|
|
@@ -83,7 +83,7 @@ def health_mongo() -> str:
|
|
| 83 |
app_logger.error(str(pme))
|
| 84 |
db_ok["mongo_ok"] = False
|
| 85 |
raise HTTPException("mongo not ok!")
|
| 86 |
-
return f"
|
| 87 |
|
| 88 |
|
| 89 |
@app.post("/words-frequency")
|
|
@@ -184,6 +184,14 @@ except Exception as ex_mount_static:
|
|
| 184 |
if not API_MODE:
|
| 185 |
app_logger.exception(f"since API_MODE is {API_MODE} we will raise the exception!")
|
| 186 |
raise ex_mount_static
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
# add the CorrelationIdMiddleware AFTER the @app.middleware("http") decorated function to avoid missing request id
|
| 189 |
app.add_middleware(CorrelationIdMiddleware)
|
|
|
|
| 4 |
from datetime import datetime
|
| 5 |
|
| 6 |
import requests
|
|
|
|
| 7 |
import uvicorn
|
| 8 |
from asgi_correlation_id import CorrelationIdMiddleware
|
| 9 |
from fastapi import FastAPI, Request
|
|
|
|
| 15 |
from pymongo.errors import PyMongoError
|
| 16 |
|
| 17 |
from my_ghost_writer import pymongo_operations_rw, exception_handlers
|
| 18 |
+
from my_ghost_writer.constants import (app_logger, ALLOWED_ORIGIN_LIST, API_MODE, DOMAIN, IS_TESTING, STATIC_FOLDER,
|
| 19 |
+
WORDSAPI_KEY, WORDSAPI_URL, RAPIDAPI_HOST, ME_CONFIG_MONGODB_USE_OK, ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP,
|
| 20 |
+
STATIC_FOLDER_LITEKOBOLDAINET, LOG_LEVEL, PORT)
|
| 21 |
from my_ghost_writer.pymongo_utils import mongodb_health_check
|
| 22 |
from my_ghost_writer.text_parsers import text_stemming
|
| 23 |
from my_ghost_writer.type_hints import RequestTextFrequencyBody, RequestQueryThesaurusWordsapiBody
|
| 24 |
|
| 25 |
|
| 26 |
async def mongo_health_check_background_task():
|
| 27 |
+
app_logger.info(f"starting task, ME_CONFIG_MONGODB_USE_OK:{ME_CONFIG_MONGODB_USE_OK}...")
|
| 28 |
+
while ME_CONFIG_MONGODB_USE_OK:
|
| 29 |
try:
|
| 30 |
db_ok["mongo_ok"] = health_mongo() == "Mongodb: still alive..."
|
| 31 |
except PyMongoError:
|
| 32 |
db_ok["mongo_ok"] = False
|
| 33 |
+
await asyncio.sleep(ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP)
|
| 34 |
|
| 35 |
|
| 36 |
async def lifespan(app: FastAPI):
|
|
|
|
| 52 |
allow_credentials=True,
|
| 53 |
allow_methods=["GET", "POST"]
|
| 54 |
)
|
| 55 |
+
db_ok = {"mongo_ok": ME_CONFIG_MONGODB_USE_OK}
|
| 56 |
|
| 57 |
|
| 58 |
@app.middleware("http")
|
|
|
|
| 75 |
@app.get("/health-mongo")
|
| 76 |
def health_mongo() -> str:
|
| 77 |
app_logger.info(f"pymongo driver version:{pymongo_version}!")
|
| 78 |
+
if ME_CONFIG_MONGODB_USE_OK:
|
| 79 |
try:
|
| 80 |
db_ok["mongo_ok"] = mongodb_health_check()
|
| 81 |
return "Mongodb: still alive..."
|
|
|
|
| 83 |
app_logger.error(str(pme))
|
| 84 |
db_ok["mongo_ok"] = False
|
| 85 |
raise HTTPException("mongo not ok!")
|
| 86 |
+
return f"ME_CONFIG_MONGODB_USE_OK:{ME_CONFIG_MONGODB_USE_OK}..."
|
| 87 |
|
| 88 |
|
| 89 |
@app.post("/words-frequency")
|
|
|
|
| 184 |
if not API_MODE:
|
| 185 |
app_logger.exception(f"since API_MODE is {API_MODE} we will raise the exception!")
|
| 186 |
raise ex_mount_static
|
| 187 |
+
try:
|
| 188 |
+
app.mount("/lite.koboldai.net", StaticFiles(directory=STATIC_FOLDER_LITEKOBOLDAINET, html=True), name="lite.koboldai.net")
|
| 189 |
+
except Exception as ex_mount_static1:
|
| 190 |
+
app_logger.error(
|
| 191 |
+
f"Failed to mount static folder: {STATIC_FOLDER_LITEKOBOLDAINET}, exception: {ex_mount_static1}, API_MODE: {API_MODE}!")
|
| 192 |
+
if not API_MODE:
|
| 193 |
+
app_logger.exception(f"since API_MODE is {API_MODE} we will raise the exception!")
|
| 194 |
+
raise ex_mount_static1
|
| 195 |
|
| 196 |
# add the CorrelationIdMiddleware AFTER the @app.middleware("http") decorated function to avoid missing request id
|
| 197 |
app.add_middleware(CorrelationIdMiddleware)
|
my_ghost_writer/constants.py
CHANGED
|
@@ -9,7 +9,9 @@ from my_ghost_writer import session_logger
|
|
| 9 |
load_dotenv()
|
| 10 |
PROJECT_ROOT_FOLDER = Path(__file__).parent.parent
|
| 11 |
STATIC_FOLDER = PROJECT_ROOT_FOLDER / "static"
|
|
|
|
| 12 |
STATIC_FOLDER = Path(os.getenv("STATIC_FOLDER", str(STATIC_FOLDER)))
|
|
|
|
| 13 |
DOMAIN=os.getenv("DOMAIN", "localhost")
|
| 14 |
PORT=int(os.getenv("PORT", 7860))
|
| 15 |
ALLOWED_ORIGIN_LIST = os.getenv('ALLOWED_ORIGIN', f'http://{DOMAIN}:{PORT}').split(",")
|
|
@@ -21,16 +23,13 @@ N_WORDS_GRAM = int(os.getenv("N_WORDS_GRAM", 2))
|
|
| 21 |
WORDSAPI_KEY = os.getenv("WORDSAPI_KEY")
|
| 22 |
WORDSAPI_URL = os.getenv("WORDSAPI_URL", "https://wordsapiv1.p.rapidapi.com/words")
|
| 23 |
RAPIDAPI_HOST = os.getenv("RAPIDAPI_HOST", "wordsapiv1.p.rapidapi.com")
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
MONGO_CONNECTION_TIMEOUT_LOCAL if MONGO_CONNECTION_STRING == MONGO_CONNECTION_STRING_LOCAL else MONGO_CONNECTION_TIMEOUT_REMOTE
|
| 32 |
-
))
|
| 33 |
-
MONGO_HEALTHCHECK_SLEEP = int(os.getenv("MONGO_HEALTHCHECK_SLEEP", 900))
|
| 34 |
DEFAULT_DBNAME_THESAURUS = "thesaurus"
|
| 35 |
DEFAULT_COLLECTION_THESAURUS =os.getenv("DEFAULT_COLLECTION_THESAURUS", "wordsapi")
|
| 36 |
session_logger.setup_logging(json_logs=LOG_JSON_FORMAT, log_level=LOG_LEVEL)
|
|
|
|
| 9 |
load_dotenv()
|
| 10 |
PROJECT_ROOT_FOLDER = Path(__file__).parent.parent
|
| 11 |
STATIC_FOLDER = PROJECT_ROOT_FOLDER / "static"
|
| 12 |
+
STATIC_FOLDER_LITEKOBOLDAINET = PROJECT_ROOT_FOLDER / "lite.koboldai.net"
|
| 13 |
STATIC_FOLDER = Path(os.getenv("STATIC_FOLDER", str(STATIC_FOLDER)))
|
| 14 |
+
STATIC_FOLDER_LITEKOBOLDAINET = Path(os.getenv("STATIC_FOLDER_LITEKOBOLDAINET", str(STATIC_FOLDER_LITEKOBOLDAINET)))
|
| 15 |
DOMAIN=os.getenv("DOMAIN", "localhost")
|
| 16 |
PORT=int(os.getenv("PORT", 7860))
|
| 17 |
ALLOWED_ORIGIN_LIST = os.getenv('ALLOWED_ORIGIN', f'http://{DOMAIN}:{PORT}').split(",")
|
|
|
|
| 23 |
WORDSAPI_KEY = os.getenv("WORDSAPI_KEY")
|
| 24 |
WORDSAPI_URL = os.getenv("WORDSAPI_URL", "https://wordsapiv1.p.rapidapi.com/words")
|
| 25 |
RAPIDAPI_HOST = os.getenv("RAPIDAPI_HOST", "wordsapiv1.p.rapidapi.com")
|
| 26 |
+
ME_CONFIG_MONGODB_USE_OK = bool(os.getenv("ME_CONFIG_MONGODB_USE_OK", ""))
|
| 27 |
+
ME_CONFIG_MONGODB_URL_LOCAL = "mongodb://localhost:27017"
|
| 28 |
+
ME_CONFIG_MONGODB_URL = os.getenv("ME_CONFIG_MONGODB_URL", ME_CONFIG_MONGODB_URL_LOCAL)
|
| 29 |
+
ME_CONFIG_MONGODB_TIMEOUT_LOCAL = int(os.getenv("ME_CONFIG_MONGODB_TIMEOUT_LOCAL", 200))
|
| 30 |
+
ME_CONFIG_MONGODB_TIMEOUT_REMOTE = int(os.getenv("ME_CONFIG_MONGODB_TIMEOUT_REMOTE", 3000))
|
| 31 |
+
ME_CONFIG_MONGODB_TIMEOUT = int(os.getenv( "ME_CONFIG_MONGODB_TIMEOUT", ME_CONFIG_MONGODB_TIMEOUT_LOCAL if ME_CONFIG_MONGODB_URL == ME_CONFIG_MONGODB_URL_LOCAL else ME_CONFIG_MONGODB_TIMEOUT_REMOTE))
|
| 32 |
+
ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP = int(os.getenv("ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP", 900))
|
|
|
|
|
|
|
|
|
|
| 33 |
DEFAULT_DBNAME_THESAURUS = "thesaurus"
|
| 34 |
DEFAULT_COLLECTION_THESAURUS =os.getenv("DEFAULT_COLLECTION_THESAURUS", "wordsapi")
|
| 35 |
session_logger.setup_logging(json_logs=LOG_JSON_FORMAT, log_level=LOG_LEVEL)
|
my_ghost_writer/pymongo_utils.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
from pymongo import MongoClient
|
| 2 |
|
| 3 |
-
from my_ghost_writer.constants import DEFAULT_DBNAME_THESAURUS,
|
| 4 |
|
| 5 |
|
| 6 |
def get_client() -> MongoClient:
|
| 7 |
-
client = MongoClient(
|
| 8 |
return client
|
| 9 |
|
| 10 |
|
|
|
|
| 1 |
from pymongo import MongoClient
|
| 2 |
|
| 3 |
+
from my_ghost_writer.constants import DEFAULT_DBNAME_THESAURUS, ME_CONFIG_MONGODB_URL, DEFAULT_COLLECTION_THESAURUS, ME_CONFIG_MONGODB_TIMEOUT, app_logger
|
| 4 |
|
| 5 |
|
| 6 |
def get_client() -> MongoClient:
|
| 7 |
+
client = MongoClient(ME_CONFIG_MONGODB_URL, timeoutMS=ME_CONFIG_MONGODB_TIMEOUT)
|
| 8 |
return client
|
| 9 |
|
| 10 |
|
poetry.lock
CHANGED
|
@@ -18,7 +18,7 @@ version = "4.9.0"
|
|
| 18 |
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
| 19 |
optional = false
|
| 20 |
python-versions = ">=3.9"
|
| 21 |
-
groups = ["
|
| 22 |
files = [
|
| 23 |
{file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"},
|
| 24 |
{file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"},
|
|
@@ -66,6 +66,108 @@ files = [
|
|
| 66 |
{file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"},
|
| 67 |
]
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
[[package]]
|
| 70 |
name = "click"
|
| 71 |
version = "8.1.8"
|
|
@@ -179,7 +281,7 @@ version = "2.7.0"
|
|
| 179 |
description = "DNS toolkit"
|
| 180 |
optional = false
|
| 181 |
python-versions = ">=3.9"
|
| 182 |
-
groups = ["
|
| 183 |
files = [
|
| 184 |
{file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"},
|
| 185 |
{file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"},
|
|
@@ -200,7 +302,7 @@ version = "1.2.2"
|
|
| 200 |
description = "Backport of PEP 654 (exception groups)"
|
| 201 |
optional = false
|
| 202 |
python-versions = ">=3.7"
|
| 203 |
-
groups = ["
|
| 204 |
markers = "python_version == \"3.10\""
|
| 205 |
files = [
|
| 206 |
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
|
@@ -237,7 +339,7 @@ version = "0.14.0"
|
|
| 237 |
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
| 238 |
optional = false
|
| 239 |
python-versions = ">=3.7"
|
| 240 |
-
groups = ["
|
| 241 |
files = [
|
| 242 |
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
| 243 |
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
|
@@ -249,7 +351,7 @@ version = "1.0.8"
|
|
| 249 |
description = "A minimal low-level HTTP client."
|
| 250 |
optional = false
|
| 251 |
python-versions = ">=3.8"
|
| 252 |
-
groups = ["
|
| 253 |
files = [
|
| 254 |
{file = "httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be"},
|
| 255 |
{file = "httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad"},
|
|
@@ -271,7 +373,7 @@ version = "0.28.1"
|
|
| 271 |
description = "The next generation HTTP client."
|
| 272 |
optional = false
|
| 273 |
python-versions = ">=3.8"
|
| 274 |
-
groups = ["
|
| 275 |
files = [
|
| 276 |
{file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"},
|
| 277 |
{file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"},
|
|
@@ -523,7 +625,7 @@ version = "4.13.2"
|
|
| 523 |
description = "PyMongo - the Official MongoDB Python driver"
|
| 524 |
optional = false
|
| 525 |
python-versions = ">=3.9"
|
| 526 |
-
groups = ["
|
| 527 |
files = [
|
| 528 |
{file = "pymongo-4.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:01065eb1838e3621a30045ab14d1a60ee62e01f65b7cf154e69c5c722ef14d2f"},
|
| 529 |
{file = "pymongo-4.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ab0325d436075f5f1901cde95afae811141d162bc42d9a5befb647fda585ae6"},
|
|
@@ -597,21 +699,6 @@ snappy = ["python-snappy"]
|
|
| 597 |
test = ["pytest (>=8.2)", "pytest-asyncio (>=0.24.0)"]
|
| 598 |
zstd = ["zstandard"]
|
| 599 |
|
| 600 |
-
[[package]]
|
| 601 |
-
name = "pymongo-inmemory"
|
| 602 |
-
version = "0.5.0"
|
| 603 |
-
description = "A mongo mocking library with an ephemeral MongoDB running in memory."
|
| 604 |
-
optional = false
|
| 605 |
-
python-versions = "<4.0,>=3.9"
|
| 606 |
-
groups = ["test"]
|
| 607 |
-
files = [
|
| 608 |
-
{file = "pymongo_inmemory-0.5.0-py3-none-any.whl", hash = "sha256:ebad4ccc9d9bed859ad25932f039aadb476f29c6945df57fdba0f9171f6626a1"},
|
| 609 |
-
{file = "pymongo_inmemory-0.5.0.tar.gz", hash = "sha256:2af2a6bab1cda9a27f524737ce6d3c9ff8cb9e52c224537e5742d610c4aa677e"},
|
| 610 |
-
]
|
| 611 |
-
|
| 612 |
-
[package.dependencies]
|
| 613 |
-
pymongo = "*"
|
| 614 |
-
|
| 615 |
[[package]]
|
| 616 |
name = "pytest"
|
| 617 |
version = "8.3.5"
|
|
@@ -773,13 +860,35 @@ files = [
|
|
| 773 |
{file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"},
|
| 774 |
]
|
| 775 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 776 |
[[package]]
|
| 777 |
name = "sniffio"
|
| 778 |
version = "1.3.1"
|
| 779 |
description = "Sniff out which async library your code is running under"
|
| 780 |
optional = false
|
| 781 |
python-versions = ">=3.7"
|
| 782 |
-
groups = ["
|
| 783 |
files = [
|
| 784 |
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
| 785 |
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
|
@@ -900,7 +1009,7 @@ files = [
|
|
| 900 |
{file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"},
|
| 901 |
{file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"},
|
| 902 |
]
|
| 903 |
-
markers = {main = "python_version
|
| 904 |
|
| 905 |
[[package]]
|
| 906 |
name = "typing-inspection"
|
|
@@ -917,6 +1026,24 @@ files = [
|
|
| 917 |
[package.dependencies]
|
| 918 |
typing-extensions = ">=4.12.0"
|
| 919 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 920 |
[[package]]
|
| 921 |
name = "uvicorn"
|
| 922 |
version = "0.34.2"
|
|
@@ -940,4 +1067,4 @@ standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)
|
|
| 940 |
[metadata]
|
| 941 |
lock-version = "2.1"
|
| 942 |
python-versions = ">=3.10,<4.0.0"
|
| 943 |
-
content-hash = "
|
|
|
|
| 18 |
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
| 19 |
optional = false
|
| 20 |
python-versions = ">=3.9"
|
| 21 |
+
groups = ["test", "webserver"]
|
| 22 |
files = [
|
| 23 |
{file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"},
|
| 24 |
{file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"},
|
|
|
|
| 66 |
{file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"},
|
| 67 |
]
|
| 68 |
|
| 69 |
+
[[package]]
|
| 70 |
+
name = "charset-normalizer"
|
| 71 |
+
version = "3.4.2"
|
| 72 |
+
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
| 73 |
+
optional = false
|
| 74 |
+
python-versions = ">=3.7"
|
| 75 |
+
groups = ["main"]
|
| 76 |
+
files = [
|
| 77 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"},
|
| 78 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"},
|
| 79 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"},
|
| 80 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"},
|
| 81 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"},
|
| 82 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"},
|
| 83 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"},
|
| 84 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"},
|
| 85 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"},
|
| 86 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"},
|
| 87 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"},
|
| 88 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"},
|
| 89 |
+
{file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"},
|
| 90 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"},
|
| 91 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"},
|
| 92 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"},
|
| 93 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"},
|
| 94 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"},
|
| 95 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"},
|
| 96 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"},
|
| 97 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"},
|
| 98 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"},
|
| 99 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"},
|
| 100 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"},
|
| 101 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"},
|
| 102 |
+
{file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"},
|
| 103 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"},
|
| 104 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"},
|
| 105 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"},
|
| 106 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"},
|
| 107 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"},
|
| 108 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"},
|
| 109 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"},
|
| 110 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"},
|
| 111 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"},
|
| 112 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"},
|
| 113 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"},
|
| 114 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"},
|
| 115 |
+
{file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"},
|
| 116 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"},
|
| 117 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"},
|
| 118 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"},
|
| 119 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"},
|
| 120 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"},
|
| 121 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"},
|
| 122 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"},
|
| 123 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"},
|
| 124 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"},
|
| 125 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"},
|
| 126 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"},
|
| 127 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"},
|
| 128 |
+
{file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"},
|
| 129 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"},
|
| 130 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"},
|
| 131 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"},
|
| 132 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"},
|
| 133 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"},
|
| 134 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"},
|
| 135 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"},
|
| 136 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"},
|
| 137 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"},
|
| 138 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"},
|
| 139 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"},
|
| 140 |
+
{file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"},
|
| 141 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"},
|
| 142 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"},
|
| 143 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"},
|
| 144 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"},
|
| 145 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"},
|
| 146 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"},
|
| 147 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"},
|
| 148 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"},
|
| 149 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"},
|
| 150 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"},
|
| 151 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"},
|
| 152 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"},
|
| 153 |
+
{file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"},
|
| 154 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"},
|
| 155 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"},
|
| 156 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"},
|
| 157 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"},
|
| 158 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"},
|
| 159 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"},
|
| 160 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"},
|
| 161 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"},
|
| 162 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"},
|
| 163 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"},
|
| 164 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"},
|
| 165 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"},
|
| 166 |
+
{file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"},
|
| 167 |
+
{file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"},
|
| 168 |
+
{file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"},
|
| 169 |
+
]
|
| 170 |
+
|
| 171 |
[[package]]
|
| 172 |
name = "click"
|
| 173 |
version = "8.1.8"
|
|
|
|
| 281 |
description = "DNS toolkit"
|
| 282 |
optional = false
|
| 283 |
python-versions = ">=3.9"
|
| 284 |
+
groups = ["webserver"]
|
| 285 |
files = [
|
| 286 |
{file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"},
|
| 287 |
{file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"},
|
|
|
|
| 302 |
description = "Backport of PEP 654 (exception groups)"
|
| 303 |
optional = false
|
| 304 |
python-versions = ">=3.7"
|
| 305 |
+
groups = ["test", "webserver"]
|
| 306 |
markers = "python_version == \"3.10\""
|
| 307 |
files = [
|
| 308 |
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
|
|
|
| 339 |
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
| 340 |
optional = false
|
| 341 |
python-versions = ">=3.7"
|
| 342 |
+
groups = ["test", "webserver"]
|
| 343 |
files = [
|
| 344 |
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
| 345 |
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
|
|
|
| 351 |
description = "A minimal low-level HTTP client."
|
| 352 |
optional = false
|
| 353 |
python-versions = ">=3.8"
|
| 354 |
+
groups = ["test"]
|
| 355 |
files = [
|
| 356 |
{file = "httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be"},
|
| 357 |
{file = "httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad"},
|
|
|
|
| 373 |
description = "The next generation HTTP client."
|
| 374 |
optional = false
|
| 375 |
python-versions = ">=3.8"
|
| 376 |
+
groups = ["test"]
|
| 377 |
files = [
|
| 378 |
{file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"},
|
| 379 |
{file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"},
|
|
|
|
| 625 |
description = "PyMongo - the Official MongoDB Python driver"
|
| 626 |
optional = false
|
| 627 |
python-versions = ">=3.9"
|
| 628 |
+
groups = ["webserver"]
|
| 629 |
files = [
|
| 630 |
{file = "pymongo-4.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:01065eb1838e3621a30045ab14d1a60ee62e01f65b7cf154e69c5c722ef14d2f"},
|
| 631 |
{file = "pymongo-4.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ab0325d436075f5f1901cde95afae811141d162bc42d9a5befb647fda585ae6"},
|
|
|
|
| 699 |
test = ["pytest (>=8.2)", "pytest-asyncio (>=0.24.0)"]
|
| 700 |
zstd = ["zstandard"]
|
| 701 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 702 |
[[package]]
|
| 703 |
name = "pytest"
|
| 704 |
version = "8.3.5"
|
|
|
|
| 860 |
{file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"},
|
| 861 |
]
|
| 862 |
|
| 863 |
+
[[package]]
|
| 864 |
+
name = "requests"
|
| 865 |
+
version = "2.32.4"
|
| 866 |
+
description = "Python HTTP for Humans."
|
| 867 |
+
optional = false
|
| 868 |
+
python-versions = ">=3.8"
|
| 869 |
+
groups = ["main"]
|
| 870 |
+
files = [
|
| 871 |
+
{file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"},
|
| 872 |
+
{file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"},
|
| 873 |
+
]
|
| 874 |
+
|
| 875 |
+
[package.dependencies]
|
| 876 |
+
certifi = ">=2017.4.17"
|
| 877 |
+
charset_normalizer = ">=2,<4"
|
| 878 |
+
idna = ">=2.5,<4"
|
| 879 |
+
urllib3 = ">=1.21.1,<3"
|
| 880 |
+
|
| 881 |
+
[package.extras]
|
| 882 |
+
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
| 883 |
+
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
| 884 |
+
|
| 885 |
[[package]]
|
| 886 |
name = "sniffio"
|
| 887 |
version = "1.3.1"
|
| 888 |
description = "Sniff out which async library your code is running under"
|
| 889 |
optional = false
|
| 890 |
python-versions = ">=3.7"
|
| 891 |
+
groups = ["test", "webserver"]
|
| 892 |
files = [
|
| 893 |
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
| 894 |
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
|
|
|
| 1009 |
{file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"},
|
| 1010 |
{file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"},
|
| 1011 |
]
|
| 1012 |
+
markers = {main = "python_version == \"3.10\"", test = "python_version < \"3.13\""}
|
| 1013 |
|
| 1014 |
[[package]]
|
| 1015 |
name = "typing-inspection"
|
|
|
|
| 1026 |
[package.dependencies]
|
| 1027 |
typing-extensions = ">=4.12.0"
|
| 1028 |
|
| 1029 |
+
[[package]]
|
| 1030 |
+
name = "urllib3"
|
| 1031 |
+
version = "2.5.0"
|
| 1032 |
+
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
| 1033 |
+
optional = false
|
| 1034 |
+
python-versions = ">=3.9"
|
| 1035 |
+
groups = ["main"]
|
| 1036 |
+
files = [
|
| 1037 |
+
{file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
|
| 1038 |
+
{file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
|
| 1039 |
+
]
|
| 1040 |
+
|
| 1041 |
+
[package.extras]
|
| 1042 |
+
brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
|
| 1043 |
+
h2 = ["h2 (>=4,<5)"]
|
| 1044 |
+
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
| 1045 |
+
zstd = ["zstandard (>=0.18.0)"]
|
| 1046 |
+
|
| 1047 |
[[package]]
|
| 1048 |
name = "uvicorn"
|
| 1049 |
version = "0.34.2"
|
|
|
|
| 1067 |
[metadata]
|
| 1068 |
lock-version = "2.1"
|
| 1069 |
python-versions = ">=3.10,<4.0.0"
|
| 1070 |
+
content-hash = "b578e3a1f51339d719e4a980386129cba38f47c0f8b9f4a2ce405885125624b3"
|
pyproject.toml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
[project]
|
| 2 |
name = "my-ghost-writer"
|
| 3 |
-
version = "0.
|
| 4 |
-
description = "A simple
|
| 5 |
authors = [
|
| 6 |
{name = "alessandro trinca tornidor",email = "[email protected]"}
|
| 7 |
]
|
|
@@ -12,14 +12,13 @@ dependencies = [
|
|
| 12 |
"nltk (>=3.9.1,<4.0.0)",
|
| 13 |
"python-dotenv (>=1.1.0,<2.0.0)",
|
| 14 |
"structlog (>=25.2.0,<26.0.0)",
|
| 15 |
-
"
|
| 16 |
]
|
| 17 |
|
| 18 |
[tool.poetry.group.test]
|
| 19 |
optional = true
|
| 20 |
|
| 21 |
[tool.poetry.group.test.dependencies]
|
| 22 |
-
pymongo-inmemory = "^0.5.0"
|
| 23 |
pytest = "^8.3.5"
|
| 24 |
pytest-cov = "^6.1.1"
|
| 25 |
httpx = "^0.28.1"
|
|
|
|
| 1 |
[project]
|
| 2 |
name = "my-ghost-writer"
|
| 3 |
+
version = "0.4.0"
|
| 4 |
+
description = "A simple webapp supporting writers"
|
| 5 |
authors = [
|
| 6 |
{name = "alessandro trinca tornidor",email = "[email protected]"}
|
| 7 |
]
|
|
|
|
| 12 |
"nltk (>=3.9.1,<4.0.0)",
|
| 13 |
"python-dotenv (>=1.1.0,<2.0.0)",
|
| 14 |
"structlog (>=25.2.0,<26.0.0)",
|
| 15 |
+
"requests (>=2.32.4,<3.0.0)"
|
| 16 |
]
|
| 17 |
|
| 18 |
[tool.poetry.group.test]
|
| 19 |
optional = true
|
| 20 |
|
| 21 |
[tool.poetry.group.test.dependencies]
|
|
|
|
| 22 |
pytest = "^8.3.5"
|
| 23 |
pytest-cov = "^6.1.1"
|
| 24 |
httpx = "^0.28.1"
|
requirements_poetry.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
poetry==2.1.3
|
template.env
CHANGED
|
@@ -4,11 +4,11 @@ ALLOWED_ORIGIN=http://localhost:7860,http://localhost:8000
|
|
| 4 |
WORDSAPI_KEY=
|
| 5 |
WORDSAPI_URL=https://wordsapiv1.p.rapidapi.com/words
|
| 6 |
RAPIDAPI_HOST=wordsapiv1.p.rapidapi.com
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
DEFAULT_COLLECTION_THESAURUS=wordsapi
|
|
|
|
| 4 |
WORDSAPI_KEY=
|
| 5 |
WORDSAPI_URL=https://wordsapiv1.p.rapidapi.com/words
|
| 6 |
RAPIDAPI_HOST=wordsapiv1.p.rapidapi.com
|
| 7 |
+
ME_CONFIG_MONGODB_USE_OK=
|
| 8 |
+
ME_CONFIG_MONGODB_URL_LOCAL=mongodb://localhost:27017
|
| 9 |
+
ME_CONFIG_MONGODB_URL=mongodb://localhost:27017
|
| 10 |
+
ME_CONFIG_MONGODB_TIMEOUT_LOCAL=200
|
| 11 |
+
ME_CONFIG_MONGODB_TIMEOUT_REMOTE=3000
|
| 12 |
+
ME_CONFIG_MONGODB_TIMEOUT=
|
| 13 |
+
ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP=900
|
| 14 |
DEFAULT_COLLECTION_THESAURUS=wordsapi
|
tests/test_app.py
CHANGED
|
@@ -148,7 +148,7 @@ class TestAppEndpoints(unittest.TestCase):
|
|
| 148 |
|
| 149 |
def test_mongo_health_check_background_task(self):
|
| 150 |
# Patch sleep and health_mongo to exit after one loop
|
| 151 |
-
with patch("my_ghost_writer.app.
|
| 152 |
patch("my_ghost_writer.app.health_mongo", return_value="Mongodb: still alive..."), \
|
| 153 |
patch("my_ghost_writer.app.asyncio.sleep", side_effect=Exception("stop")):
|
| 154 |
with self.assertRaises(Exception):
|
|
|
|
| 148 |
|
| 149 |
def test_mongo_health_check_background_task(self):
|
| 150 |
# Patch sleep and health_mongo to exit after one loop
|
| 151 |
+
with patch("my_ghost_writer.app.ME_CONFIG_MONGODB_USE_OK", True), \
|
| 152 |
patch("my_ghost_writer.app.health_mongo", return_value="Mongodb: still alive..."), \
|
| 153 |
patch("my_ghost_writer.app.asyncio.sleep", side_effect=Exception("stop")):
|
| 154 |
with self.assertRaises(Exception):
|
tests/test_pymongo_utils.py
CHANGED
|
@@ -9,8 +9,8 @@ class TestPymongoUtils(unittest.TestCase):
|
|
| 9 |
def test_get_client(self, mock_mongo_client):
|
| 10 |
client = pymongo_utils.get_client()
|
| 11 |
mock_mongo_client.assert_called_with(
|
| 12 |
-
pymongo_utils.
|
| 13 |
-
timeoutMS=pymongo_utils.
|
| 14 |
)
|
| 15 |
self.assertEqual(client, mock_mongo_client.return_value)
|
| 16 |
|
|
|
|
| 9 |
def test_get_client(self, mock_mongo_client):
|
| 10 |
client = pymongo_utils.get_client()
|
| 11 |
mock_mongo_client.assert_called_with(
|
| 12 |
+
pymongo_utils.ME_CONFIG_MONGODB_URL,
|
| 13 |
+
timeoutMS=pymongo_utils.ME_CONFIG_MONGODB_TIMEOUT
|
| 14 |
)
|
| 15 |
self.assertEqual(client, mock_mongo_client.return_value)
|
| 16 |
|