diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69bd238..0ee485e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,12 +12,13 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: astral-sh/setup-uv@v5 with: + enable-cache: true python-version: ${{ matrix.python-version }} - name: Install tokenizers @@ -31,21 +32,16 @@ jobs: git apply ./24.patch && ./configure && \ sudo make && sudo make install && sudo ldconfig -v - - run: python -m pip install --upgrade pip - - run: pip install .[all] + - name: Install dependencies + run: uv sync --group dev --all-extras - run: | - pip install ruff - ruff check src - ruff format --diff src + uv run ruff check src + uv run ruff format --diff src - - run: | - pip install mypy types-requests - mypy src + - run: uv run mypy src - - run: | - pip install pytest httpx - pytest + - run: uv run pytest env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/Dockerfile b/Dockerfile index 5fb79d5..b5cd239 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,9 @@ RUN apt update -y \ python3-pip \ && rm -rf /var/lib/apt/lists/* +# uv +COPY --from=ghcr.io/astral-sh/uv:0.6.17 /uv /uvx /bin/ + WORKDIR /tmp # kytea @@ -32,18 +35,29 @@ RUN tar zxvf kytea-0.4.7.tar.gz \ WORKDIR /work -COPY ./data ./data -COPY ./src ./src -COPY ./pyproject.toml ./pyproject.toml -COPY ./requirements.lock ./requirements.lock -COPY ./README.md ./README.md +ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy + +# install dependencies +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +ADD ./data /work +ADD ./src /work +ADD ./pyproject.toml /work +ADD ./uv.lock /work +ADD ./README.md /work + +# install project +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --all-extras -RUN python3.10 -m pip install -U pip -RUN python3.10 -m pip install -r requirements.lock -RUN python3.10 -m pip install . +ENV PATH="/work/.venv/bin:$PATH" CMD [ \ - "python3.10", "-m", "uvicorn", \ + "uvicorn", \ "--factory", "konoha.api.server:create_app", \ "--reload", "--host", "0.0.0.0", "--port", "8000" \ ] diff --git a/pyproject.toml b/pyproject.toml index a34d464..5dbfa6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,15 +71,19 @@ module = [ ] ignore_missing_imports = true -[tool.uv] -dev-dependencies = [ +[dependency-groups] +dev = [ "pytest>=8.2.0", "httpx>=0.27.0", "ruff>=0.4.4", "mypy>=1.10.0", "sphinx>=7.3.7", "pydata-sphinx-theme>=0.16.1", + "types-requests>=2.31.0.6", ] +[tool.uv] +default-groups = ["dev"] + [tool.ruff] line-length = 119 diff --git a/requirements-dev.lock b/requirements-dev.lock deleted file mode 100644 index 62aa5db..0000000 --- a/requirements-dev.lock +++ /dev/null @@ -1,211 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: true -# with-sources: false - --e file:. -accessible-pygments==0.0.5 - # via pydata-sphinx-theme -alabaster==0.7.16 - # via sphinx -annotated-types==0.6.0 - # via pydantic -anyio==4.3.0 - # via httpx - # via starlette - # via watchfiles -babel==2.15.0 - # via pydata-sphinx-theme - # via sphinx -beautifulsoup4==4.12.3 - # via pydata-sphinx-theme -boto3==1.34.103 - # via konoha -botocore==1.34.103 - # via boto3 - # via s3transfer -certifi==2024.2.2 - # via httpcore - # via httpx - # via requests -cffi==1.16.0 - # via natto-py -charset-normalizer==3.3.2 - # via requests -click==8.1.7 - # via typer - # via uvicorn -cython==3.0.10 - # via dynet38 -dnspython==2.6.1 - # via email-validator -docutils==0.21.2 - # via pydata-sphinx-theme - # via sphinx -dynet38==2.2 - # via nagisa -email-validator==2.1.1 - # via fastapi -exceptiongroup==1.2.1 - # via anyio - # via pytest -fastapi==0.111.0 - # via fastapi-cli - # via konoha -fastapi-cli==0.0.3 - # via fastapi -h11==0.14.0 - # via httpcore - # via uvicorn -httpcore==1.0.5 - # via httpx -httptools==0.6.1 - # via uvicorn -httpx==0.27.0 - # via fastapi -idna==3.7 - # via anyio - # via email-validator - # via httpx - # via requests -imagesize==1.4.1 - # via sphinx -importlib-metadata==7.1.0 - # via sphinx -iniconfig==2.0.0 - # via pytest -janome==0.5.0 - # via konoha -jinja2==3.1.4 - # via fastapi - # via sphinx -jmespath==1.0.1 - # via boto3 - # via botocore -kytea==0.1.9 - # via konoha -markdown-it-py==3.0.0 - # via rich -markupsafe==2.1.5 - # via jinja2 -mdurl==0.1.2 - # via markdown-it-py -mypy==1.10.0 -mypy-extensions==1.0.0 - # via mypy -nagisa==0.2.11 - # via konoha -natto-py==1.0.1 - # via konoha -numpy==1.26.4 - # via dynet38 - # via nagisa -orjson==3.10.3 - # via fastapi -packaging==24.0 - # via pydata-sphinx-theme - # via pytest - # via sphinx -pluggy==1.5.0 - # via pytest -pycparser==2.22 - # via cffi -pydantic==2.7.1 - # via fastapi -pydantic-core==2.18.2 - # via pydantic -pydata-sphinx-theme==0.15.2 -pygments==2.18.0 - # via accessible-pygments - # via pydata-sphinx-theme - # via rich - # via sphinx -pytest==8.2.0 -python-dateutil==2.9.0.post0 - # via botocore -python-dotenv==1.0.1 - # via uvicorn -python-multipart==0.0.9 - # via fastapi -pyyaml==6.0.1 - # via uvicorn -requests==2.31.0 - # via konoha - # via sphinx -rich==13.7.1 - # via typer -ruff==0.4.4 -s3transfer==0.10.1 - # via boto3 -sentencepiece==0.1.99 - # via konoha -shellingham==1.5.4 - # via typer -six==1.16.0 - # via nagisa - # via python-dateutil -sniffio==1.3.1 - # via anyio - # via httpx -snowballstemmer==2.2.0 - # via sphinx -soupsieve==2.5 - # via beautifulsoup4 -sphinx==7.3.7 - # via pydata-sphinx-theme -sphinxcontrib-applehelp==1.0.8 - # via sphinx -sphinxcontrib-devhelp==1.0.6 - # via sphinx -sphinxcontrib-htmlhelp==2.0.5 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==1.0.7 - # via sphinx -sphinxcontrib-serializinghtml==1.1.10 - # via sphinx -starlette==0.37.2 - # via fastapi -sudachidict-core==20230927 - # via konoha -sudachipy==0.6.8 - # via konoha - # via sudachidict-core -tomli==2.0.1 - # via mypy - # via pytest - # via sphinx -typer==0.12.3 - # via fastapi-cli -typing-extensions==4.11.0 - # via anyio - # via fastapi - # via mypy - # via pydantic - # via pydantic-core - # via pydata-sphinx-theme - # via starlette - # via typer - # via uvicorn -ujson==5.9.0 - # via fastapi -urllib3==1.26.18 - # via botocore - # via requests -uvicorn==0.25.0 - # via fastapi - # via fastapi-cli - # via konoha -uvloop==0.19.0 - # via uvicorn -watchfiles==0.21.0 - # via uvicorn -websockets==12.0 - # via uvicorn -zipp==3.18.1 - # via importlib-metadata diff --git a/requirements.lock b/requirements.lock deleted file mode 100644 index c76c19c..0000000 --- a/requirements.lock +++ /dev/null @@ -1,149 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: true -# with-sources: false - --e file:. -annotated-types==0.6.0 - # via pydantic -anyio==4.3.0 - # via httpx - # via starlette - # via watchfiles -boto3==1.34.103 - # via konoha -botocore==1.34.103 - # via boto3 - # via s3transfer -certifi==2024.2.2 - # via httpcore - # via httpx - # via requests -cffi==1.16.0 - # via natto-py -charset-normalizer==3.3.2 - # via requests -click==8.1.7 - # via typer - # via uvicorn -cython==3.0.10 - # via dynet38 -dnspython==2.6.1 - # via email-validator -dynet38==2.2 - # via nagisa -email-validator==2.1.1 - # via fastapi -exceptiongroup==1.2.1 - # via anyio -fastapi==0.111.0 - # via fastapi-cli - # via konoha -fastapi-cli==0.0.3 - # via fastapi -h11==0.14.0 - # via httpcore - # via uvicorn -httpcore==1.0.5 - # via httpx -httptools==0.6.1 - # via uvicorn -httpx==0.27.0 - # via fastapi -idna==3.7 - # via anyio - # via email-validator - # via httpx - # via requests -janome==0.5.0 - # via konoha -jinja2==3.1.4 - # via fastapi -jmespath==1.0.1 - # via boto3 - # via botocore -kytea==0.1.9 - # via konoha -markdown-it-py==3.0.0 - # via rich -markupsafe==2.1.5 - # via jinja2 -mdurl==0.1.2 - # via markdown-it-py -nagisa==0.2.11 - # via konoha -natto-py==1.0.1 - # via konoha -numpy==1.26.4 - # via dynet38 - # via nagisa -orjson==3.10.3 - # via fastapi -pycparser==2.22 - # via cffi -pydantic==2.7.1 - # via fastapi -pydantic-core==2.18.2 - # via pydantic -pygments==2.18.0 - # via rich -python-dateutil==2.9.0.post0 - # via botocore -python-dotenv==1.0.1 - # via uvicorn -python-multipart==0.0.9 - # via fastapi -pyyaml==6.0.1 - # via uvicorn -requests==2.31.0 - # via konoha -rich==13.7.1 - # via typer -s3transfer==0.10.1 - # via boto3 -sentencepiece==0.1.99 - # via konoha -shellingham==1.5.4 - # via typer -six==1.16.0 - # via nagisa - # via python-dateutil -sniffio==1.3.1 - # via anyio - # via httpx -starlette==0.37.2 - # via fastapi -sudachidict-core==20230927 - # via konoha -sudachipy==0.6.8 - # via konoha - # via sudachidict-core -typer==0.12.3 - # via fastapi-cli -typing-extensions==4.11.0 - # via anyio - # via fastapi - # via pydantic - # via pydantic-core - # via starlette - # via typer - # via uvicorn -ujson==5.9.0 - # via fastapi -urllib3==1.26.18 - # via botocore - # via requests -uvicorn==0.25.0 - # via fastapi - # via fastapi-cli - # via konoha -uvloop==0.19.0 - # via uvicorn -watchfiles==0.21.0 - # via uvicorn -websockets==12.0 - # via uvicorn diff --git a/uv.lock b/uv.lock index b913af0..b3455e5 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,4 @@ version = 1 -revision = 1 requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.11'", @@ -581,6 +580,8 @@ dev = [ { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "types-requests", version = "2.31.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "types-requests", version = "2.32.0.20250328", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] [package.metadata] @@ -606,7 +607,6 @@ requires-dist = [ { name = "uvicorn", marker = "extra == 'all'", specifier = "<0.26.0" }, { name = "uvicorn", marker = "extra == 'server'", specifier = "<0.26.0" }, ] -provides-extras = ["server", "all", "remote", "janome", "kytea", "nagisa", "mecab", "sentencepiece", "sudachi"] [package.metadata.requires-dev] dev = [ @@ -616,6 +616,7 @@ dev = [ { name = "pytest", specifier = ">=8.2.0" }, { name = "ruff", specifier = ">=0.4.4" }, { name = "sphinx", specifier = ">=7.3.7" }, + { name = "types-requests", specifier = ">=2.31.0.6" }, ] [[package]] @@ -1514,6 +1515,46 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, ] +[[package]] +name = "types-requests" +version = "2.31.0.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "types-urllib3", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/b8/c1e8d39996b4929b918aba10dba5de07a8b3f4c8487bb61bb79882544e69/types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0", size = 15535 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/a1/6f8dc74d9069e790d604ddae70cb46dcbac668f1bb08136e7b0f2f5cd3bf/types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9", size = 14516 }, +] + +[[package]] +name = "types-requests" +version = "2.32.0.20250328" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "urllib3", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/7d/eb174f74e3f5634eaacb38031bbe467dfe2e545bc255e5c90096ec46bc46/types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32", size = 22995 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/15/3700282a9d4ea3b37044264d3e4d1b1f0095a4ebf860a99914fd544e3be3/types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2", size = 20663 }, +] + +[[package]] +name = "types-urllib3" +version = "1.26.25.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/de/b9d7a68ad39092368fb21dd6194b362b98a1daeea5dcfef5e1adb5031c7e/types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f", size = 11239 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/7b/3fc711b2efea5e85a7a0bbfe269ea944aa767bbba5ec52f9ee45d362ccf3/types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e", size = 15377 }, +] + [[package]] name = "typing-extensions" version = "4.13.2"