Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

strategy:
matrix:
python-version: ["3.12"]
python-version: ["3.14"]
max-parallel: 4

# Steps represent a sequence of tasks that will be executed as part of the job
Expand Down Expand Up @@ -87,7 +87,7 @@ jobs:
sudo apt upgrade -y

# install req packages
sudo apt install -y --no-install-recommends python3-all-dev python3-dev python3-pip python${{ matrix.python-version }} python${{ matrix.python-version }}-dev
sudo apt install -y --no-install-recommends python3-all-dev python3-dev python3-pip
sudo apt -y --no-install-recommends -o Dpkg::Options::="--force-confold" -y -o Dpkg::Options::="--force-confdef" -fuy dist-upgrade
sudo apt install -y --no-install-recommends \
gnupg \
Expand Down Expand Up @@ -148,12 +148,12 @@ jobs:
- name: Install python deps & create virtual environment
run: |

# BEFORE creating the venv so /usr/bin/python3.12 can run unoserver
# BEFORE creating the venv so the distro Python can run unoserver
# the reason for this is that the uno python bindings are tied to the system python
# and will not work in a venv
# so we need to install unoserver globally to match the version in requirements.txt
# this is a bit hacky but it works around the issue of unoserver not being available
# via pip for python3.12 (as of 2025-08)
# via pip for the distro Python used by LibreOffice/UNO
set -eux

UNOSERVER_PIN=$(awk -F'==' '/^unoserver==/ {print $2; exit}' requirements.txt || true)
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:
run: |
export OCR_SERVICE_LOG_LEVEL=10
export OCR_SERVICE_DEBUG_MODE=True
export LIBRE_OFFICE_PYTHON_PATH=/usr/bin/python3.12
export LIBRE_OFFICE_PYTHON_PATH=/usr/bin/python3
export OCR_TMP_DIR=${{ github.workspace }}/tmp
source venv/bin/activate
python -m unittest discover -s ocr_service/tests -p 'test_process.py'
Expand Down
20 changes: 10 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ubuntu:noble
FROM ubuntu:26.04

ARG APP_PYTHON_VERSION=3.13
ARG LO_PYTHON_VERSION=3.12
ARG APP_PYTHON_VERSION=3.14
ARG LO_PYTHON_VERSION=3.14

ARG HTTP_PROXY
ARG HTTPS_PROXY
Expand Down Expand Up @@ -45,7 +45,6 @@ RUN apt-get -o Acquire::Retries=5 update -yq && \
# add extra repos
RUN apt-add-repository -y -n multiverse && \
apt-add-repository -y -n universe && \
add-apt-repository -y -n ppa:deadsnakes/ppa && \
add-apt-repository -y -n ppa:graphics-drivers/ppa && \
apt-get -o Acquire::Retries=5 update -yq && \
apt-get upgrade -y
Expand Down Expand Up @@ -88,9 +87,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends fontconfig ttf-
libsm6 libxext6 gstreamer1.0-libav fonts-deva fonts-dejavu fonts-gfs-didot fonts-gfs-didot-classic fonts-junicode fonts-ebgaramond fonts-noto-cjk fonts-takao-gothic fonts-vlgothic \
ghostscript ghostscript-x gsfonts gsfonts-other gsfonts-x11 fonts-croscore fonts-crosextra-caladea fonts-crosextra-carlito fonts-liberation fonts-open-sans fonts-noto-core fonts-ibm-plex fonts-urw-base35 \
fonts-noto fonts-noto-cjk fonts-noto-extra xfonts-terminus fonts-font-awesome fonts-hack fonts-inconsolata fonts-liberation2 fonts-mononoki \
libpcre3 libpcre3-dev libxml2 libxml2-dev libxslt1.1 libxslt-dev \
libpcre2-8-0 libpcre2-dev libxml2-16 libxml2-dev libxslt1.1 libxslt-dev \
mesa-opencl-icd pocl-opencl-icd libvips-tools libvips libvips-dev \
imagemagick libcairo2-dev tesseract-ocr tesseract-ocr-all libtesseract5 libtesseract-dev libleptonica-dev liblept5
imagemagick libcairo2-dev tesseract-ocr tesseract-ocr-all libtesseract5 libtesseract-dev libleptonica-dev libleptonica6

# tessaract language packages
RUN apt-get install -y --no-install-recommends --fix-missing tesseract-ocr-osd tesseract-ocr-lat \
Expand Down Expand Up @@ -127,12 +126,12 @@ COPY ./ /ocr_service
WORKDIR /ocr_service

# --- Install system-wide unoserver to match requirements.txt (for UNO/system Python) ---
# BEFORE creating the venv so /usr/bin/python3.12 can run unoserver
# BEFORE creating the venv so the distro Python can run unoserver
# the reason for this is that the uno python bindings are tied to the system python
# and will not work in a venv
# so we need to install unoserver globally to match the version in requirements.txt
# this is a bit hacky but it works around the issue of unoserver not being available
# via pip for the system python (3.12 on Ubuntu noble)
# via pip for the system Python used by LibreOffice/UNO
RUN UNOSERVER_PIN=$(awk -F'==' '/^unoserver==/ {print $2; exit}' requirements.txt || true) && \
if [ -n "$UNOSERVER_PIN" ]; then \
echo "Installing system unoserver==$UNOSERVER_PIN"; \
Expand All @@ -146,9 +145,9 @@ RUN UNOSERVER_PIN=$(awk -F'==' '/^unoserver==/ {print $2; exit}' requirements.tx
# Use a virtual environment for Python deps (single-stage build)
ENV VIRTUAL_ENV=/opt/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV LIBRE_OFFICE_PYTHON_PATH=/usr/bin/python3.12
ENV LIBRE_OFFICE_PYTHON_PATH=/usr/bin/python${LO_PYTHON_VERSION}

# Install the application into a Python 3.13 virtual environment while
# Install the application into a separate virtual environment while
# keeping LibreOffice/UNO on the system Python.
RUN python${APP_PYTHON_VERSION} -m venv "$VIRTUAL_ENV" && \
"$VIRTUAL_ENV/bin/python" && \
Expand All @@ -164,6 +163,7 @@ ARG OCR_SERVICE_GID=10001
RUN groupadd --system --gid "$OCR_SERVICE_GID" ocrsvc && \
useradd --system --uid "$OCR_SERVICE_UID" --gid "$OCR_SERVICE_GID" --create-home --home-dir /home/ocrsvc --shell /usr/sbin/nologin ocrsvc && \
mkdir -p /ocr_service/tmp /ocr_service/log && \
chmod -R a+rX /ocr_service && \
chown -R ocrsvc:ocrsvc /ocr_service/tmp /ocr_service/log /home/ocrsvc
ENV HOME=/home/ocrsvc
USER ocrsvc
Expand Down
2 changes: 1 addition & 1 deletion ocr_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def model_post_init(self, __context: Any) -> None:

if platform in ("linux", "linux2"):
default_lo_exec = "/usr/bin/soffice"
default_lo_python = "/usr/bin/python3.12"
default_lo_python = "/usr/bin/python3"
tessdata_prefix = "/usr/share/tesseract-ocr/5/tessdata"

if not os.path.exists(tessdata_prefix):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ html2image==2.0.7
tesserocr==2.9.2
gunicorn==23.0.0
pypdfium2==5.9.0
opencv-python-headless==4.12.0.88
opencv-python-headless==4.13.0.92
pyxml2pdf==0.3.4
fastapi==0.116.1
orjson==3.11.6
Expand Down
12 changes: 7 additions & 5 deletions start_service_debug.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,16 @@ echo "==========================================================================

python_version=python3

if command -v python3.11 &>/dev/null; then
python_version=python3.11
elif command -v python3.12 &>/dev/null; then
python_version=python3.12
if command -v python3.14 &>/dev/null; then
python_version=python3.14
elif command -v python3.13 &>/dev/null; then
python_version=python3.13
elif command -v python3.12 &>/dev/null; then
python_version=python3.12
elif command -v python3.11 &>/dev/null; then
python_version=python3.11
else
echo "Python 3.11, 3.12, or 3.13 is required. Please install one of them."
echo "Python 3.11, 3.12, 3.13, or 3.14 is required. Please install one of them."
exit 1
fi

Expand Down
9 changes: 5 additions & 4 deletions start_service_production.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ if [[ -x "$VIRTUAL_ENV/bin/gunicorn" ]]; then
else
# Fallback to system python if venv missing
python_cmd=python3
if command -v python3.12 &>/dev/null; then
if command -v python3.14 &>/dev/null; then
python_cmd=python3.14
elif command -v python3.13 &>/dev/null; then
python_cmd=python3.13
elif command -v python3.12 &>/dev/null; then
python_cmd=python3.12
elif command -v python3.11 &>/dev/null; then
python_cmd=python3.11
elif command -v python3.13 &>/dev/null; then
python_cmd=python3.13
fi
gunicorn_cmd=("$python_cmd" "-m" "gunicorn")
fi
Expand All @@ -60,4 +62,3 @@ exec "${gunicorn_cmd[@]}" wsgi:app --worker-class "$OCR_SERVICE_WORKER_CLASS" \
--max-requests-jitter "$OCR_SERVICE_GUNICORN_MAX_REQUESTS_JITTER" \
--timeout "$OCR_SERVICE_GUNICORN_TIMEOUT" \
--graceful-timeout "$OCR_SERVICE_GUNICORN_GRACEFUL_TIMEOUT"

Loading