mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 02:15:06 +00:00
chore(deps): upgrade backend deps within their declared ranges
`uv lock --upgrade` plus the two code changes the new versions need.
firecrawl-anydoc 0.2.4 raises a dedicated `NeedsOcrError` where 0.2.3 raised
`UnsupportedError("... OCR is required")`, so the anydoc parser no longer
recognised a scanned PDF: the fallback still ran, but a near-empty result was
stored as an empty document instead of failing with the OCR_ENABLED hint.
`_needs_ocr` now accepts both spellings and looks the class up lazily, so an
older anydoc keeps working. 0.2.4 also refuses the CID-font NDA fixture
outright rather than dropping its Chinese column silently, so the PDF
trust-check tests stub that dropped output against the fixture's real bytes
(the check's own inputs) and a new test pins the refusal path.
ruff 0.16 widened its implicit default rule set, turning the dev-group bump
into 7131 findings across the tree. `.ruff.toml` now states the historical
selection (E4, E7, E9, F) explicitly and the CI pin moves to the locked
0.16.7, so lint no longer drifts with the version.
This commit is contained in:
1 parent
0d461d10a7
commit
7e00197678
9 files changed
+916
-810
No files matched your search
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Lint with Ruff
|
||||
uses: chartboost/ruff-action@v1
|
||||
with:
|
||||
version: 0.14.10
|
||||
version: 0.16.7
|
||||
|
||||
requirements-in-sync:
|
||||
# application/requirements*.txt are exported from uv.lock; fail when a
|
||||
|
||||
+8
-1
@@ -1,6 +1,13 @@
|
||||
# Allow lines to be as long as 120 characters.
|
||||
line-length = 120
|
||||
|
||||
[lint]
|
||||
# Ruff's historical default rule set, stated explicitly: 0.16 widened the
|
||||
# implicit default (pyupgrade and friends), which silently turns a linter
|
||||
# upgrade into thousands of findings across the tree. Adding rules is a
|
||||
# deliberate change, not a side effect of bumping the pin.
|
||||
select = ["E4", "E7", "E9", "F"]
|
||||
|
||||
[lint.per-file-ignores]
|
||||
# Integration tests use sys.path.insert() before imports for standalone execution
|
||||
"tests/integration/*.py" = ["E402"]
|
||||
"tests/integration/*.py" = ["E402"]
|
||||
@@ -9,11 +9,11 @@ of 2.3 GB, with equivalent output on clean office files, CSV and text-layer
|
||||
PDFs.
|
||||
|
||||
anydoc never OCRs. It *detects* a scanned or image-only PDF and raises
|
||||
``UnsupportedError`` ("OCR is required"), which is the routing point: a
|
||||
parser given a ``fallback_parser`` (docling when installed, the native OCR
|
||||
parser when OCR is on without docling, otherwise the legacy parser for the
|
||||
suffix) delegates there; without one the file fails loudly as
|
||||
``DocumentParseError`` rather than being stored empty.
|
||||
``NeedsOcrError`` (``UnsupportedError`` "OCR is required" before 0.2.4),
|
||||
which is the routing point: a parser given a ``fallback_parser`` (docling
|
||||
when installed, the native OCR parser when OCR is on without docling,
|
||||
otherwise the legacy parser for the suffix) delegates there; without one the
|
||||
file fails loudly as ``DocumentParseError`` rather than being stored empty.
|
||||
"""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
|
||||
# not content.
|
||||
_MIN_SCAN_FALLBACK_CHARS = 50
|
||||
|
||||
# Suffixes anydoc 0.2.3 converts, verified with ``anydoc.format_from_extension``.
|
||||
# Suffixes anydoc 0.2.4 converts, verified with ``anydoc.format_from_extension``.
|
||||
# ``.epub`` is deliberately absent: it stays on ``EpubParser``.
|
||||
ANYDOC_SUFFIXES: Tuple[str, ...] = (
|
||||
# Word processing
|
||||
@@ -91,6 +91,22 @@ def _result_chars(result: Union[str, List[str]]) -> int:
|
||||
return len(str(result).strip())
|
||||
|
||||
|
||||
def _needs_ocr(exc: Exception) -> bool:
|
||||
"""Whether an ``anydoc.ConvertError`` means "text exists but needs OCR".
|
||||
|
||||
anydoc 0.2.4 raises a dedicated ``NeedsOcrError`` for a PDF with no text
|
||||
layer; 0.2.3 raised ``UnsupportedError`` with "OCR" in the message. Both
|
||||
spellings route the same way, and the class is looked up lazily so an
|
||||
anydoc without it still works.
|
||||
"""
|
||||
import anydoc
|
||||
|
||||
needs_ocr_error = getattr(anydoc, "NeedsOcrError", None)
|
||||
if needs_ocr_error is not None and isinstance(exc, needs_ocr_error):
|
||||
return True
|
||||
return isinstance(exc, anydoc.UnsupportedError) and "OCR" in str(exc)
|
||||
|
||||
|
||||
def _is_docling_backed(parser: Optional[BaseParser]) -> bool:
|
||||
"""True when ``parser`` is a docling parser (worth a trust-check re-parse).
|
||||
|
||||
@@ -191,11 +207,10 @@ class AnydocParser(BaseParser):
|
||||
) from exc
|
||||
except anydoc.ConvertError as exc:
|
||||
# Typed, per-document failures another engine may still handle:
|
||||
# UnsupportedError (scanned PDF / unknown format), MalformedError,
|
||||
# EncryptedError, MissingPartError.
|
||||
ocr_needed = isinstance(exc, anydoc.UnsupportedError) and "OCR" in str(exc)
|
||||
# NeedsOcrError (scanned PDF), UnsupportedError (unknown format),
|
||||
# MalformedError, EncryptedError, MissingPartError.
|
||||
return self._delegate(
|
||||
path, errors, f"{type(exc).__name__}: {exc}", ocr_needed=ocr_needed
|
||||
path, errors, f"{type(exc).__name__}: {exc}", ocr_needed=_needs_ocr(exc)
|
||||
)
|
||||
except OSError as exc:
|
||||
raise DocumentParseError(
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
|
||||
a2wsgi==1.10.10
|
||||
# via docsgpt
|
||||
accelerate==1.14.0
|
||||
# via
|
||||
# docling-ibm-models
|
||||
# docling-slim
|
||||
accelerate==1.15.0
|
||||
# via docling-slim
|
||||
aiofile==3.12.3
|
||||
# via py-key-value-aio
|
||||
aiofiles==25.1.0
|
||||
@@ -43,7 +41,7 @@ aiohttp-retry==2.9.1
|
||||
# daytona-toolbox-api-client-async
|
||||
aiosignal==1.4.0
|
||||
# via aiohttp
|
||||
alembic==1.19.2
|
||||
alembic==1.20.0
|
||||
# via docsgpt
|
||||
amqp==5.3.1
|
||||
# via kombu
|
||||
@@ -75,7 +73,6 @@ attrs==26.1.0
|
||||
# via
|
||||
# aiohttp
|
||||
# cyclopts
|
||||
# jsonlines
|
||||
# jsonschema
|
||||
# jsonschema-path
|
||||
# referencing
|
||||
@@ -94,15 +91,15 @@ billiard==4.2.4
|
||||
# via celery
|
||||
blinker==1.9.0
|
||||
# via flask
|
||||
boto3==1.43.67
|
||||
boto3==1.43.93
|
||||
# via docsgpt
|
||||
botocore==1.43.89
|
||||
botocore==1.43.93
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
cachetools==7.1.8
|
||||
# via py-key-value-aio
|
||||
caio==0.12.2
|
||||
caio==0.12.4
|
||||
# via aiofile
|
||||
cel-python==0.5.0
|
||||
# via docsgpt
|
||||
@@ -152,7 +149,7 @@ colorlog==6.12.0
|
||||
# via rapidocr
|
||||
croniter==6.2.4
|
||||
# via docsgpt
|
||||
cryptography==50.0.0
|
||||
cryptography==50.0.1
|
||||
# via
|
||||
# authlib
|
||||
# docsgpt
|
||||
@@ -161,7 +158,7 @@ cryptography==50.0.0
|
||||
# msal
|
||||
# pyjwt
|
||||
# secretstorage
|
||||
cyclopts==4.24.0
|
||||
cyclopts==4.25.2
|
||||
# via fastmcp-slim
|
||||
dataclasses-json==0.6.7
|
||||
# via docsgpt
|
||||
@@ -202,18 +199,17 @@ dnspython==2.8.0
|
||||
# via email-validator
|
||||
doclang==0.7.3
|
||||
# via docling-core
|
||||
docling==2.119.0
|
||||
docling==2.126.0
|
||||
# via docsgpt
|
||||
docling-core==2.95.0
|
||||
docling-core==2.96.0
|
||||
# via
|
||||
# docling-ibm-models
|
||||
# docling-parse
|
||||
# docling-slim
|
||||
docling-ibm-models==3.15.0
|
||||
docling-ibm-models==4.0.2
|
||||
# via docling-slim
|
||||
docling-parse==7.17.0
|
||||
docling-parse==7.19.1
|
||||
# via docling-slim
|
||||
docling-slim==2.119.0
|
||||
docling-slim==2.126.0
|
||||
# via docling
|
||||
docstring-parser==0.18.0
|
||||
# via
|
||||
@@ -223,7 +219,7 @@ docx2txt==0.9
|
||||
# via docsgpt
|
||||
ecdsa==0.19.2
|
||||
# via python-jose
|
||||
elevenlabs==2.62.0
|
||||
elevenlabs==2.68.0
|
||||
# via docsgpt
|
||||
email-validator==2.3.0
|
||||
# via pydantic
|
||||
@@ -239,18 +235,18 @@ fast-ebook==0.2.0
|
||||
# via docsgpt
|
||||
fastembed==0.8.0
|
||||
# via docsgpt
|
||||
fastmcp==3.4.6
|
||||
fastmcp==3.4.7
|
||||
# via docsgpt
|
||||
fastmcp-slim==3.4.6
|
||||
fastmcp-slim==3.4.7
|
||||
# via fastmcp
|
||||
filelock==3.32.5
|
||||
filelock==3.32.6
|
||||
# via
|
||||
# huggingface-hub
|
||||
# tldextract
|
||||
# torch
|
||||
filetype==1.2.0
|
||||
# via docling-slim
|
||||
firecrawl-anydoc==0.2.3
|
||||
firecrawl-anydoc==0.2.4
|
||||
# via docsgpt
|
||||
flask==3.1.3
|
||||
# via
|
||||
@@ -270,9 +266,9 @@ fsspec==2026.7.0
|
||||
# torch
|
||||
google-api-core==2.36.0
|
||||
# via google-api-python-client
|
||||
google-api-python-client==2.198.0
|
||||
google-api-python-client==2.200.0
|
||||
# via docsgpt
|
||||
google-auth==2.57.1
|
||||
google-auth==2.58.0
|
||||
# via
|
||||
# google-api-core
|
||||
# google-api-python-client
|
||||
@@ -281,9 +277,9 @@ google-auth==2.57.1
|
||||
# google-genai
|
||||
google-auth-httplib2==0.4.2
|
||||
# via google-api-python-client
|
||||
google-auth-oauthlib==1.4.0
|
||||
google-auth-oauthlib==1.4.1
|
||||
# via docsgpt
|
||||
google-genai==2.17.0
|
||||
google-genai==2.23.0
|
||||
# via docsgpt
|
||||
google-re2==1.1.20251105
|
||||
# via cel-python
|
||||
@@ -302,7 +298,7 @@ grpcio==1.83.1
|
||||
# qdrant-client
|
||||
gtts==2.5.4
|
||||
# via docsgpt
|
||||
gunicorn==26.0.0
|
||||
gunicorn==26.2.0
|
||||
# via
|
||||
# docsgpt
|
||||
# uvicorn-worker
|
||||
@@ -381,7 +377,7 @@ jinja2==3.1.6
|
||||
# docsgpt
|
||||
# flask
|
||||
# torch
|
||||
jiter==0.16.0
|
||||
jiter==0.17.0
|
||||
# via
|
||||
# anthropic
|
||||
# openai
|
||||
@@ -394,8 +390,6 @@ joserfc==1.7.5
|
||||
# via
|
||||
# authlib
|
||||
# fastmcp-slim
|
||||
jsonlines==4.0.0
|
||||
# via docling-ibm-models
|
||||
jsonref==1.1.0
|
||||
# via
|
||||
# docling-core
|
||||
@@ -423,7 +417,7 @@ kombu==5.6.2
|
||||
# docsgpt
|
||||
lark==1.3.1
|
||||
# via cel-python
|
||||
latex2mathml==3.81.0
|
||||
latex2mathml==3.81.1
|
||||
# via docling-core
|
||||
lazy-object-proxy==1.12.0
|
||||
# via openapi-spec-validator
|
||||
@@ -435,7 +429,7 @@ lxml==6.1.3
|
||||
# doclang
|
||||
# python-docx
|
||||
# python-pptx
|
||||
mail-parser==4.6.4
|
||||
mail-parser==4.6.5
|
||||
# via docling-slim
|
||||
mako==1.4.1
|
||||
# via alembic
|
||||
@@ -453,7 +447,7 @@ markupsafe==3.0.3
|
||||
# werkzeug
|
||||
marshmallow==3.26.2
|
||||
# via dataclasses-json
|
||||
mcp==1.29.1
|
||||
mcp==1.30.0
|
||||
# via fastmcp-slim
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
@@ -467,9 +461,9 @@ mpire==2.10.2
|
||||
# via semchunk
|
||||
mpmath==1.3.0
|
||||
# via sympy
|
||||
msal==1.37.0
|
||||
msal==1.38.0
|
||||
# via docsgpt
|
||||
multidict==6.7.1
|
||||
multidict==6.8.0
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
@@ -481,7 +475,7 @@ networkx==3.6.1
|
||||
# via
|
||||
# docsgpt
|
||||
# torch
|
||||
numpy==2.5.1
|
||||
numpy==2.5.3
|
||||
# via
|
||||
# accelerate
|
||||
# docling-ibm-models
|
||||
@@ -507,11 +501,11 @@ olefile==0.47
|
||||
# via python-oxmsg
|
||||
omegaconf==2.3.1
|
||||
# via rapidocr
|
||||
onnxruntime==1.28.0
|
||||
onnxruntime==1.30.0
|
||||
# via
|
||||
# docsgpt
|
||||
# fastembed
|
||||
openai==2.53.0
|
||||
openai==2.54.0
|
||||
# via docsgpt
|
||||
openapi-pydantic==0.5.1
|
||||
# via fastmcp-slim
|
||||
@@ -519,7 +513,7 @@ openapi-schema-validator==0.9.0
|
||||
# via openapi-spec-validator
|
||||
openapi-spec-validator==0.9.0
|
||||
# via openapi3-parser
|
||||
openapi3-parser==1.1.22
|
||||
openapi3-parser==1.3.0
|
||||
# via docsgpt
|
||||
opencv-python==5.0.0.93
|
||||
# via rapidocr
|
||||
@@ -642,7 +636,6 @@ packaging==26.3
|
||||
# accelerate
|
||||
# faiss-cpu
|
||||
# fastmcp-slim
|
||||
# gunicorn
|
||||
# huggingface-hub
|
||||
# kombu
|
||||
# marshmallow
|
||||
@@ -676,7 +669,7 @@ pillow==12.3.0
|
||||
# python-pptx
|
||||
# rapidocr
|
||||
# torchvision
|
||||
platformdirs==4.11.7
|
||||
platformdirs==4.11.8
|
||||
# via fastmcp-slim
|
||||
pluggy==1.6.0
|
||||
# via docling-slim
|
||||
@@ -686,7 +679,7 @@ portalocker==3.2.0
|
||||
# via qdrant-client
|
||||
prance==26.7.19.0
|
||||
# via openapi3-parser
|
||||
praw==8.0.2
|
||||
praw==8.0.3
|
||||
# via docsgpt
|
||||
prawcore==4.0.0
|
||||
# via praw
|
||||
@@ -744,7 +737,6 @@ pydantic==2.13.5
|
||||
# daytona-toolbox-api-client
|
||||
# daytona-toolbox-api-client-async
|
||||
# docling-core
|
||||
# docling-ibm-models
|
||||
# docling-parse
|
||||
# docling-slim
|
||||
# docsgpt
|
||||
@@ -776,7 +768,7 @@ pygments==2.21.0
|
||||
# mpire
|
||||
# rich
|
||||
# rich-rst
|
||||
pyjwt==2.13.0
|
||||
pyjwt==2.14.0
|
||||
# via
|
||||
# mcp
|
||||
# msal
|
||||
@@ -784,9 +776,9 @@ pylatexenc==2.11
|
||||
# via docling-slim
|
||||
pyparsing==3.3.2
|
||||
# via httplib2
|
||||
pypdf==6.15.0
|
||||
pypdf==6.18.1
|
||||
# via docsgpt
|
||||
pypdfium2==5.12.1
|
||||
pypdfium2==5.13.0
|
||||
# via
|
||||
# docling-slim
|
||||
# docsgpt
|
||||
@@ -861,7 +853,7 @@ rapidocr==3.9.2
|
||||
# via
|
||||
# docling-slim
|
||||
# docsgpt
|
||||
redis==7.4.0
|
||||
redis==7.4.1
|
||||
# via
|
||||
# celery-redbeat
|
||||
# docsgpt
|
||||
@@ -872,7 +864,7 @@ referencing==0.37.0
|
||||
# jsonschema-path
|
||||
# jsonschema-specifications
|
||||
# openapi-schema-validator
|
||||
regex==2026.9.3
|
||||
regex==2026.9.10
|
||||
# via
|
||||
# tiktoken
|
||||
# transformers
|
||||
@@ -920,9 +912,7 @@ rpds-py==2026.6.3
|
||||
rsa==4.9.1
|
||||
# via python-jose
|
||||
rtree==1.4.1
|
||||
# via
|
||||
# docling-ibm-models
|
||||
# docling-slim
|
||||
# via docling-slim
|
||||
ruamel-yaml==0.19.1
|
||||
# via prance
|
||||
s3transfer==0.19.2
|
||||
@@ -1017,9 +1007,8 @@ torchvision==0.26.0+cpu ; sys_platform == 'linux'
|
||||
# docling-ibm-models
|
||||
# docling-slim
|
||||
# docsgpt
|
||||
tqdm==4.67.3
|
||||
tqdm==4.70.1
|
||||
# via
|
||||
# docling-ibm-models
|
||||
# docling-slim
|
||||
# docsgpt
|
||||
# fastembed
|
||||
@@ -1103,7 +1092,7 @@ typing-inspection==0.4.4
|
||||
# mcp
|
||||
# pydantic
|
||||
# pydantic-settings
|
||||
tzdata==2026.3
|
||||
tzdata==2026.4
|
||||
# via
|
||||
# faker
|
||||
# kombu
|
||||
@@ -1149,7 +1138,7 @@ watchfiles==1.2.0
|
||||
# uvicorn
|
||||
wcwidth==0.8.3
|
||||
# via prompt-toolkit
|
||||
websocket-client==1.9.0
|
||||
websocket-client==1.9.2
|
||||
# via
|
||||
# docsgpt
|
||||
# praw
|
||||
@@ -1168,7 +1157,7 @@ werkzeug==3.1.8
|
||||
# flask-restx
|
||||
win32-setctime==1.2.0 ; sys_platform == 'win32'
|
||||
# via loguru
|
||||
wrapt==2.4.0
|
||||
wrapt==2.4.1
|
||||
# via
|
||||
# deprecated
|
||||
# opentelemetry-instrumentation
|
||||
|
||||
@@ -27,7 +27,7 @@ aiohttp-retry==2.9.1
|
||||
# daytona-toolbox-api-client-async
|
||||
aiosignal==1.4.0
|
||||
# via aiohttp
|
||||
alembic==1.19.2
|
||||
alembic==1.20.0
|
||||
# via docsgpt
|
||||
amqp==5.3.1
|
||||
# via kombu
|
||||
@@ -74,9 +74,9 @@ billiard==4.2.4
|
||||
# via celery
|
||||
blinker==1.9.0
|
||||
# via flask
|
||||
boto3==1.43.67
|
||||
boto3==1.43.93
|
||||
# via docsgpt
|
||||
botocore==1.43.89
|
||||
botocore==1.43.93
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
@@ -84,7 +84,7 @@ cachetools==7.1.8
|
||||
# via
|
||||
# py-key-value-aio
|
||||
# pymilvus
|
||||
caio==0.12.2
|
||||
caio==0.12.4
|
||||
# via aiofile
|
||||
cel-python==0.5.0
|
||||
# via docsgpt
|
||||
@@ -129,7 +129,7 @@ colorama==0.4.6 ; sys_platform == 'win32'
|
||||
# typer
|
||||
croniter==6.2.4
|
||||
# via docsgpt
|
||||
cryptography==50.0.0
|
||||
cryptography==50.0.1
|
||||
# via
|
||||
# authlib
|
||||
# docsgpt
|
||||
@@ -138,7 +138,7 @@ cryptography==50.0.0
|
||||
# msal
|
||||
# pyjwt
|
||||
# secretstorage
|
||||
cyclopts==4.24.0
|
||||
cyclopts==4.25.2
|
||||
# via fastmcp-slim
|
||||
dataclasses-json==0.6.7
|
||||
# via docsgpt
|
||||
@@ -181,7 +181,7 @@ docx2txt==0.9
|
||||
# via docsgpt
|
||||
ecdsa==0.19.2
|
||||
# via python-jose
|
||||
elevenlabs==2.62.0
|
||||
elevenlabs==2.68.0
|
||||
# via docsgpt
|
||||
email-validator==2.3.0
|
||||
# via pydantic
|
||||
@@ -197,15 +197,15 @@ fast-ebook==0.2.0
|
||||
# via docsgpt
|
||||
fastembed==0.8.0
|
||||
# via docsgpt
|
||||
fastmcp==3.4.6
|
||||
fastmcp==3.4.7
|
||||
# via docsgpt
|
||||
fastmcp-slim==3.4.6
|
||||
fastmcp-slim==3.4.7
|
||||
# via fastmcp
|
||||
filelock==3.32.5
|
||||
filelock==3.32.6
|
||||
# via
|
||||
# huggingface-hub
|
||||
# tldextract
|
||||
firecrawl-anydoc==0.2.3
|
||||
firecrawl-anydoc==0.2.4
|
||||
# via docsgpt
|
||||
flask==3.1.3
|
||||
# via
|
||||
@@ -223,9 +223,9 @@ fsspec==2026.7.0
|
||||
# via huggingface-hub
|
||||
google-api-core==2.36.0
|
||||
# via google-api-python-client
|
||||
google-api-python-client==2.198.0
|
||||
google-api-python-client==2.200.0
|
||||
# via docsgpt
|
||||
google-auth==2.57.1
|
||||
google-auth==2.58.0
|
||||
# via
|
||||
# google-api-core
|
||||
# google-api-python-client
|
||||
@@ -234,9 +234,9 @@ google-auth==2.57.1
|
||||
# google-genai
|
||||
google-auth-httplib2==0.4.2
|
||||
# via google-api-python-client
|
||||
google-auth-oauthlib==1.4.0
|
||||
google-auth-oauthlib==1.4.1
|
||||
# via docsgpt
|
||||
google-genai==2.17.0
|
||||
google-genai==2.23.0
|
||||
# via docsgpt
|
||||
google-re2==1.1.20251105
|
||||
# via cel-python
|
||||
@@ -257,7 +257,7 @@ grpcio==1.83.1
|
||||
# qdrant-client
|
||||
gtts==2.5.4
|
||||
# via docsgpt
|
||||
gunicorn==26.0.0
|
||||
gunicorn==26.2.0
|
||||
# via
|
||||
# docsgpt
|
||||
# uvicorn-worker
|
||||
@@ -330,7 +330,7 @@ jinja2==3.1.6
|
||||
# via
|
||||
# docsgpt
|
||||
# flask
|
||||
jiter==0.16.0
|
||||
jiter==0.17.0
|
||||
# via
|
||||
# anthropic
|
||||
# openai
|
||||
@@ -389,11 +389,11 @@ markupsafe==3.0.3
|
||||
# werkzeug
|
||||
marshmallow==3.26.2
|
||||
# via dataclasses-json
|
||||
mcp==1.29.1
|
||||
mcp==1.30.0
|
||||
# via fastmcp-slim
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
milvus-lite==3.2.0 ; sys_platform != 'win32'
|
||||
milvus-lite==3.2.1 ; sys_platform != 'win32'
|
||||
# via docsgpt
|
||||
mmh3==5.3.0
|
||||
# via fastembed
|
||||
@@ -401,9 +401,9 @@ more-itertools==11.1.0
|
||||
# via
|
||||
# jaraco-classes
|
||||
# jaraco-functools
|
||||
msal==1.37.0
|
||||
msal==1.38.0
|
||||
# via docsgpt
|
||||
multidict==6.7.1
|
||||
multidict==6.8.0
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
@@ -411,7 +411,7 @@ mypy-extensions==1.1.0
|
||||
# via typing-inspect
|
||||
networkx==3.6.1
|
||||
# via docsgpt
|
||||
numpy==2.5.1
|
||||
numpy==2.5.3
|
||||
# via
|
||||
# docsgpt
|
||||
# faiss-cpu
|
||||
@@ -424,11 +424,11 @@ oauthlib==3.3.1
|
||||
# via requests-oauthlib
|
||||
obstore==0.11.1
|
||||
# via daytona
|
||||
onnxruntime==1.28.0
|
||||
onnxruntime==1.30.0
|
||||
# via
|
||||
# docsgpt
|
||||
# fastembed
|
||||
openai==2.53.0
|
||||
openai==2.54.0
|
||||
# via docsgpt
|
||||
openapi-pydantic==0.5.1
|
||||
# via fastmcp-slim
|
||||
@@ -436,7 +436,7 @@ openapi-schema-validator==0.9.0
|
||||
# via openapi-spec-validator
|
||||
openapi-spec-validator==0.9.0
|
||||
# via openapi3-parser
|
||||
openapi3-parser==1.1.22
|
||||
openapi3-parser==1.3.0
|
||||
# via docsgpt
|
||||
openpyxl==3.1.5
|
||||
# via docsgpt
|
||||
@@ -556,7 +556,6 @@ packaging==26.3
|
||||
# via
|
||||
# faiss-cpu
|
||||
# fastmcp-slim
|
||||
# gunicorn
|
||||
# huggingface-hub
|
||||
# kombu
|
||||
# marshmallow
|
||||
@@ -583,13 +582,13 @@ pillow==12.3.0
|
||||
# fastembed
|
||||
# pdf2image
|
||||
# python-pptx
|
||||
platformdirs==4.11.7
|
||||
platformdirs==4.11.8
|
||||
# via fastmcp-slim
|
||||
portalocker==3.2.0
|
||||
# via qdrant-client
|
||||
prance==26.7.19.0
|
||||
# via openapi3-parser
|
||||
praw==8.0.2
|
||||
praw==8.0.3
|
||||
# via docsgpt
|
||||
prawcore==4.0.0
|
||||
# via praw
|
||||
@@ -671,7 +670,7 @@ pygments==2.21.0
|
||||
# via
|
||||
# rich
|
||||
# rich-rst
|
||||
pyjwt==2.13.0
|
||||
pyjwt==2.14.0
|
||||
# via
|
||||
# mcp
|
||||
# msal
|
||||
@@ -679,9 +678,9 @@ pymilvus==3.0.1
|
||||
# via docsgpt
|
||||
pyparsing==3.3.2
|
||||
# via httplib2
|
||||
pypdf==6.15.0
|
||||
pypdf==6.18.1
|
||||
# via docsgpt
|
||||
pypdfium2==5.12.1
|
||||
pypdfium2==5.13.0
|
||||
# via docsgpt
|
||||
pyperclip==1.11.0
|
||||
# via fastmcp-slim
|
||||
@@ -737,7 +736,7 @@ pyyaml==6.0.3
|
||||
# uvicorn
|
||||
qdrant-client==1.19.0
|
||||
# via docsgpt
|
||||
redis==7.4.0
|
||||
redis==7.4.1
|
||||
# via
|
||||
# celery-redbeat
|
||||
# docsgpt
|
||||
@@ -748,7 +747,7 @@ referencing==0.37.0
|
||||
# jsonschema-path
|
||||
# jsonschema-specifications
|
||||
# openapi-schema-validator
|
||||
regex==2026.9.3
|
||||
regex==2026.9.10
|
||||
# via tiktoken
|
||||
requests==2.34.2
|
||||
# via
|
||||
@@ -840,7 +839,7 @@ tokenizers==0.22.2
|
||||
# fastembed
|
||||
toml==0.10.2
|
||||
# via daytona
|
||||
tqdm==4.67.3
|
||||
tqdm==4.70.1
|
||||
# via
|
||||
# docsgpt
|
||||
# fastembed
|
||||
@@ -895,7 +894,7 @@ typing-inspection==0.4.4
|
||||
# mcp
|
||||
# pydantic
|
||||
# pydantic-settings
|
||||
tzdata==2026.3
|
||||
tzdata==2026.4
|
||||
# via
|
||||
# kombu
|
||||
# pandas
|
||||
@@ -940,7 +939,7 @@ watchfiles==1.2.0
|
||||
# uvicorn
|
||||
wcwidth==0.8.3
|
||||
# via prompt-toolkit
|
||||
websocket-client==1.9.0
|
||||
websocket-client==1.9.2
|
||||
# via
|
||||
# docsgpt
|
||||
# praw
|
||||
@@ -958,7 +957,7 @@ werkzeug==3.1.8
|
||||
# flask-restx
|
||||
win32-setctime==1.2.0 ; sys_platform == 'win32'
|
||||
# via loguru
|
||||
wrapt==2.4.0
|
||||
wrapt==2.4.1
|
||||
# via
|
||||
# deprecated
|
||||
# opentelemetry-instrumentation
|
||||
|
||||
+35
-36
@@ -27,7 +27,7 @@ aiohttp-retry==2.9.1
|
||||
# daytona-toolbox-api-client-async
|
||||
aiosignal==1.4.0
|
||||
# via aiohttp
|
||||
alembic==1.19.2
|
||||
alembic==1.20.0
|
||||
# via docsgpt
|
||||
amqp==5.3.1
|
||||
# via kombu
|
||||
@@ -74,15 +74,15 @@ billiard==4.2.4
|
||||
# via celery
|
||||
blinker==1.9.0
|
||||
# via flask
|
||||
boto3==1.43.67
|
||||
boto3==1.43.93
|
||||
# via docsgpt
|
||||
botocore==1.43.89
|
||||
botocore==1.43.93
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
cachetools==7.1.8
|
||||
# via py-key-value-aio
|
||||
caio==0.12.2
|
||||
caio==0.12.4
|
||||
# via aiofile
|
||||
cel-python==0.5.0
|
||||
# via docsgpt
|
||||
@@ -127,7 +127,7 @@ colorama==0.4.6 ; sys_platform == 'win32'
|
||||
# typer
|
||||
croniter==6.2.4
|
||||
# via docsgpt
|
||||
cryptography==50.0.0
|
||||
cryptography==50.0.1
|
||||
# via
|
||||
# authlib
|
||||
# docsgpt
|
||||
@@ -136,7 +136,7 @@ cryptography==50.0.0
|
||||
# msal
|
||||
# pyjwt
|
||||
# secretstorage
|
||||
cyclopts==4.24.0
|
||||
cyclopts==4.25.2
|
||||
# via fastmcp-slim
|
||||
dataclasses-json==0.6.7
|
||||
# via docsgpt
|
||||
@@ -179,7 +179,7 @@ docx2txt==0.9
|
||||
# via docsgpt
|
||||
ecdsa==0.19.2
|
||||
# via python-jose
|
||||
elevenlabs==2.62.0
|
||||
elevenlabs==2.68.0
|
||||
# via docsgpt
|
||||
email-validator==2.3.0
|
||||
# via pydantic
|
||||
@@ -193,15 +193,15 @@ fast-ebook==0.2.0
|
||||
# via docsgpt
|
||||
fastembed==0.8.0
|
||||
# via docsgpt
|
||||
fastmcp==3.4.6
|
||||
fastmcp==3.4.7
|
||||
# via docsgpt
|
||||
fastmcp-slim==3.4.6
|
||||
fastmcp-slim==3.4.7
|
||||
# via fastmcp
|
||||
filelock==3.32.5
|
||||
filelock==3.32.6
|
||||
# via
|
||||
# huggingface-hub
|
||||
# tldextract
|
||||
firecrawl-anydoc==0.2.3
|
||||
firecrawl-anydoc==0.2.4
|
||||
# via docsgpt
|
||||
flask==3.1.3
|
||||
# via
|
||||
@@ -219,9 +219,9 @@ fsspec==2026.7.0
|
||||
# via huggingface-hub
|
||||
google-api-core==2.36.0
|
||||
# via google-api-python-client
|
||||
google-api-python-client==2.198.0
|
||||
google-api-python-client==2.200.0
|
||||
# via docsgpt
|
||||
google-auth==2.57.1
|
||||
google-auth==2.58.0
|
||||
# via
|
||||
# google-api-core
|
||||
# google-api-python-client
|
||||
@@ -230,9 +230,9 @@ google-auth==2.57.1
|
||||
# google-genai
|
||||
google-auth-httplib2==0.4.2
|
||||
# via google-api-python-client
|
||||
google-auth-oauthlib==1.4.0
|
||||
google-auth-oauthlib==1.4.1
|
||||
# via docsgpt
|
||||
google-genai==2.17.0
|
||||
google-genai==2.23.0
|
||||
# via docsgpt
|
||||
google-re2==1.1.20251105
|
||||
# via cel-python
|
||||
@@ -251,7 +251,7 @@ grpcio==1.83.1
|
||||
# qdrant-client
|
||||
gtts==2.5.4
|
||||
# via docsgpt
|
||||
gunicorn==26.0.0
|
||||
gunicorn==26.2.0
|
||||
# via
|
||||
# docsgpt
|
||||
# uvicorn-worker
|
||||
@@ -324,7 +324,7 @@ jinja2==3.1.6
|
||||
# via
|
||||
# docsgpt
|
||||
# flask
|
||||
jiter==0.16.0
|
||||
jiter==0.17.0
|
||||
# via
|
||||
# anthropic
|
||||
# openai
|
||||
@@ -383,7 +383,7 @@ markupsafe==3.0.3
|
||||
# werkzeug
|
||||
marshmallow==3.26.2
|
||||
# via dataclasses-json
|
||||
mcp==1.29.1
|
||||
mcp==1.30.0
|
||||
# via fastmcp-slim
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
@@ -393,9 +393,9 @@ more-itertools==11.1.0
|
||||
# via
|
||||
# jaraco-classes
|
||||
# jaraco-functools
|
||||
msal==1.37.0
|
||||
msal==1.38.0
|
||||
# via docsgpt
|
||||
multidict==6.7.1
|
||||
multidict==6.8.0
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
@@ -403,7 +403,7 @@ mypy-extensions==1.1.0
|
||||
# via typing-inspect
|
||||
networkx==3.6.1
|
||||
# via docsgpt
|
||||
numpy==2.5.1
|
||||
numpy==2.5.3
|
||||
# via
|
||||
# docsgpt
|
||||
# faiss-cpu
|
||||
@@ -415,11 +415,11 @@ oauthlib==3.3.1
|
||||
# via requests-oauthlib
|
||||
obstore==0.11.1
|
||||
# via daytona
|
||||
onnxruntime==1.28.0
|
||||
onnxruntime==1.30.0
|
||||
# via
|
||||
# docsgpt
|
||||
# fastembed
|
||||
openai==2.53.0
|
||||
openai==2.54.0
|
||||
# via docsgpt
|
||||
openapi-pydantic==0.5.1
|
||||
# via fastmcp-slim
|
||||
@@ -427,7 +427,7 @@ openapi-schema-validator==0.9.0
|
||||
# via openapi-spec-validator
|
||||
openapi-spec-validator==0.9.0
|
||||
# via openapi3-parser
|
||||
openapi3-parser==1.1.22
|
||||
openapi3-parser==1.3.0
|
||||
# via docsgpt
|
||||
openpyxl==3.1.5
|
||||
# via docsgpt
|
||||
@@ -545,7 +545,6 @@ packaging==26.3
|
||||
# via
|
||||
# faiss-cpu
|
||||
# fastmcp-slim
|
||||
# gunicorn
|
||||
# huggingface-hub
|
||||
# kombu
|
||||
# marshmallow
|
||||
@@ -570,13 +569,13 @@ pillow==12.3.0
|
||||
# fastembed
|
||||
# pdf2image
|
||||
# python-pptx
|
||||
platformdirs==4.11.7
|
||||
platformdirs==4.11.8
|
||||
# via fastmcp-slim
|
||||
portalocker==3.2.0
|
||||
# via qdrant-client
|
||||
prance==26.7.19.0
|
||||
# via openapi3-parser
|
||||
praw==8.0.2
|
||||
praw==8.0.3
|
||||
# via docsgpt
|
||||
prawcore==4.0.0
|
||||
# via praw
|
||||
@@ -655,15 +654,15 @@ pygments==2.21.0
|
||||
# via
|
||||
# rich
|
||||
# rich-rst
|
||||
pyjwt==2.13.0
|
||||
pyjwt==2.14.0
|
||||
# via
|
||||
# mcp
|
||||
# msal
|
||||
pyparsing==3.3.2
|
||||
# via httplib2
|
||||
pypdf==6.15.0
|
||||
pypdf==6.18.1
|
||||
# via docsgpt
|
||||
pypdfium2==5.12.1
|
||||
pypdfium2==5.13.0
|
||||
# via docsgpt
|
||||
pyperclip==1.11.0
|
||||
# via fastmcp-slim
|
||||
@@ -718,7 +717,7 @@ pyyaml==6.0.3
|
||||
# uvicorn
|
||||
qdrant-client==1.19.0
|
||||
# via docsgpt
|
||||
redis==7.4.0
|
||||
redis==7.4.1
|
||||
# via
|
||||
# celery-redbeat
|
||||
# docsgpt
|
||||
@@ -729,7 +728,7 @@ referencing==0.37.0
|
||||
# jsonschema-path
|
||||
# jsonschema-specifications
|
||||
# openapi-schema-validator
|
||||
regex==2026.9.3
|
||||
regex==2026.9.10
|
||||
# via tiktoken
|
||||
requests==2.34.2
|
||||
# via
|
||||
@@ -820,7 +819,7 @@ tokenizers==0.22.2
|
||||
# fastembed
|
||||
toml==0.10.2
|
||||
# via daytona
|
||||
tqdm==4.67.3
|
||||
tqdm==4.70.1
|
||||
# via
|
||||
# docsgpt
|
||||
# fastembed
|
||||
@@ -875,7 +874,7 @@ typing-inspection==0.4.4
|
||||
# mcp
|
||||
# pydantic
|
||||
# pydantic-settings
|
||||
tzdata==2026.3
|
||||
tzdata==2026.4
|
||||
# via
|
||||
# kombu
|
||||
# pandas
|
||||
@@ -920,7 +919,7 @@ watchfiles==1.2.0
|
||||
# uvicorn
|
||||
wcwidth==0.8.3
|
||||
# via prompt-toolkit
|
||||
websocket-client==1.9.0
|
||||
websocket-client==1.9.2
|
||||
# via
|
||||
# docsgpt
|
||||
# praw
|
||||
@@ -938,7 +937,7 @@ werkzeug==3.1.8
|
||||
# flask-restx
|
||||
win32-setctime==1.2.0 ; sys_platform == 'win32'
|
||||
# via loguru
|
||||
wrapt==2.4.0
|
||||
wrapt==2.4.1
|
||||
# via
|
||||
# deprecated
|
||||
# opentelemetry-instrumentation
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ dependencies = [
|
||||
"fast-ebook>=0.2.0,<0.3",
|
||||
# Default document converter (DOC_PARSER_ENGINE=anydoc): a Rust extension
|
||||
# with no model downloads. The docling engine is the `docling` extra.
|
||||
"firecrawl-anydoc>=0.2.3,<0.3",
|
||||
"firecrawl-anydoc>=0.2.4,<0.3",
|
||||
"fastembed>=0.8.0,<0.9",
|
||||
"fastmcp>=3.4.6,<4",
|
||||
"Flask>=3.1.3,<4",
|
||||
|
||||
@@ -79,11 +79,15 @@ def _fake_anydoc(monkeypatch, to_markdown):
|
||||
class UnsupportedError(ConvertError):
|
||||
pass
|
||||
|
||||
class NeedsOcrError(ConvertError):
|
||||
pass
|
||||
|
||||
class ResourceLimitError(ConvertError):
|
||||
pass
|
||||
|
||||
fake.ConvertError = ConvertError
|
||||
fake.UnsupportedError = UnsupportedError
|
||||
fake.NeedsOcrError = NeedsOcrError
|
||||
fake.ResourceLimitError = ResourceLimitError
|
||||
fake.to_markdown = to_markdown
|
||||
monkeypatch.setitem(sys.modules, "anydoc", fake)
|
||||
@@ -327,6 +331,22 @@ CID_PDF = FIXTURES / "nda_en_zh_cid_font.pdf"
|
||||
# Long enough to clear the near-empty guard a trust-check re-parse must pass.
|
||||
_REROUTE_TEXT = "docling reroute text, long enough to clear the near-empty reroute guard"
|
||||
|
||||
# What anydoc's CID-font silent drop looked like: the English column extracted,
|
||||
# the Chinese one gone. anydoc 0.2.4 refuses this PDF outright
|
||||
# (``test_cid_font_pdf_is_refused_as_needing_ocr``), so the trust check is
|
||||
# exercised against CID_PDF's real bytes with the dropped output stubbed in —
|
||||
# the check's own inputs, independent of which anydoc is installed.
|
||||
_CID_DROPPED_TEXT = (
|
||||
"# NON-DISCLOSURE AGREEMENT\n\nThis Agreement is entered into between the "
|
||||
"parties on the date set out below. Confidential Information shall not be "
|
||||
"disclosed to any third party."
|
||||
)
|
||||
|
||||
|
||||
def _anydoc_dropping_cjk(monkeypatch):
|
||||
"""Stub anydoc into the silent CID-font drop the trust check exists for."""
|
||||
return _fake_anydoc(monkeypatch, lambda path: _CID_DROPPED_TEXT)
|
||||
|
||||
|
||||
class _FakeDoclingFallback:
|
||||
"""Registered as a DoclingParser subclass so ``_is_docling_backed`` is True."""
|
||||
@@ -348,7 +368,20 @@ class _FakeDoclingFallback:
|
||||
return _Inner()
|
||||
|
||||
|
||||
def test_trust_flagged_pdf_reroutes_to_docling_fallback():
|
||||
def test_cid_font_pdf_is_refused_as_needing_ocr():
|
||||
"""anydoc 0.2.4 detects the unmappable CID font and raises NeedsOcrError
|
||||
rather than dropping the Chinese column silently; that must route as
|
||||
"needs OCR", which is what makes the scan guard fire."""
|
||||
fallback = _RecordingFallback(result=" ")
|
||||
fallback.ocr_enabled = False
|
||||
parser = AnydocParser(fallback_parser=fallback)
|
||||
|
||||
with pytest.raises(DocumentParseError, match="OCR_ENABLED=true"):
|
||||
parser.parse_file(CID_PDF)
|
||||
|
||||
|
||||
def test_trust_flagged_pdf_reroutes_to_docling_fallback(monkeypatch):
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
fallback = _FakeDoclingFallback()
|
||||
parser = AnydocParser(fallback_parser=fallback)
|
||||
|
||||
@@ -360,12 +393,13 @@ def test_trust_flagged_pdf_reroutes_to_docling_fallback():
|
||||
assert parser.get_file_metadata(CID_PDF) == {} # rerouted, nothing to warn about
|
||||
|
||||
|
||||
def test_trust_flagged_pdf_without_docling_keeps_output_and_warns():
|
||||
def test_trust_flagged_pdf_without_docling_keeps_output_and_warns(monkeypatch):
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
parser = AnydocParser(fallback_parser=_RecordingFallback()) # not docling-backed
|
||||
|
||||
out = parser.parse_file(CID_PDF)
|
||||
|
||||
assert "NON-DISCLOSURE" in out.upper() or len(out) > 50 # anydoc's own output kept
|
||||
assert "NON-DISCLOSURE" in out.upper() # anydoc's own output kept
|
||||
meta = parser.get_file_metadata(CID_PDF)
|
||||
assert "parse_warnings" in meta
|
||||
assert any("ToUnicode" in w for w in meta["parse_warnings"])
|
||||
@@ -377,6 +411,7 @@ def test_trust_check_disabled_stamps_nothing(monkeypatch):
|
||||
from docsgpt.parser.file import anydoc_parser as ap
|
||||
|
||||
monkeypatch.setattr(ap.settings, "PDF_TRUST_CHECK", False)
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
parser = AnydocParser()
|
||||
|
||||
parser.parse_file(CID_PDF)
|
||||
@@ -384,7 +419,8 @@ def test_trust_check_disabled_stamps_nothing(monkeypatch):
|
||||
assert parser.get_file_metadata(CID_PDF) == {}
|
||||
|
||||
|
||||
def test_trust_reroute_failure_keeps_anydoc_output():
|
||||
def test_trust_reroute_failure_keeps_anydoc_output(monkeypatch):
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
fallback = _FakeDoclingFallback()
|
||||
|
||||
def _boom(file, errors="ignore"):
|
||||
@@ -400,9 +436,10 @@ def test_trust_reroute_failure_keeps_anydoc_output():
|
||||
assert parser.last_engine == "anydoc"
|
||||
|
||||
|
||||
def test_trust_reroute_near_empty_keeps_anydoc_output():
|
||||
def test_trust_reroute_near_empty_keeps_anydoc_output(monkeypatch):
|
||||
"""A docling pipeline dropout ('' / '<!-- image -->') returns without
|
||||
raising; adopting it would swap anydoc's real text for an empty document."""
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
fallback = _FakeDoclingFallback()
|
||||
fallback.parse_file = lambda file, errors="ignore": "<!-- image -->"
|
||||
parser = AnydocParser(fallback_parser=fallback)
|
||||
@@ -414,7 +451,8 @@ def test_trust_reroute_near_empty_keeps_anydoc_output():
|
||||
assert parser.last_engine == "anydoc"
|
||||
|
||||
|
||||
def test_warnings_reset_between_files(tmp_path):
|
||||
def test_warnings_reset_between_files(monkeypatch, tmp_path):
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
parser = AnydocParser()
|
||||
parser.parse_file(CID_PDF)
|
||||
assert parser.get_file_metadata(CID_PDF) != {}
|
||||
@@ -474,6 +512,7 @@ def test_tableize_never_touches_docling_reroute(monkeypatch):
|
||||
from docsgpt.parser.file import anydoc_parser as ap
|
||||
|
||||
monkeypatch.setattr(ap.settings, "ANYDOC_TABLEIZE", True)
|
||||
_anydoc_dropping_cjk(monkeypatch)
|
||||
fallback = _FakeDoclingFallback()
|
||||
parser = AnydocParser(fallback_parser=fallback)
|
||||
|
||||
|
||||
Reference in new issue
Block a user