extract-python 0.10.4__py3-none-any.whl → 0.11.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- extract_python/__init__.py +3 -3
- extract_python/__main__.py +9 -0
- extract_python/cli/__init__.py +50 -0
- extract_python/cli/doc.py +78 -0
- extract_python/cli/utils.py +25 -0
- extract_python/docling_.py +1 -2
- {extract_python-0.10.4.dist-info → extract_python-0.11.1.dist-info}/METADATA +4 -2
- extract_python-0.11.1.dist-info/RECORD +14 -0
- extract_python-0.11.1.dist-info/entry_points.txt +2 -0
- extract_python-0.10.4.dist-info/RECORD +0 -9
- {extract_python-0.10.4.dist-info → extract_python-0.11.1.dist-info}/WHEEL +0 -0
extract_python/__init__.py
CHANGED
|
@@ -5,20 +5,20 @@ logger = logging.getLogger(__name__)
|
|
|
5
5
|
try:
|
|
6
6
|
from .docling_ import DOCLING_DEFAULT_ARTIFACTS_PATH, DoclingPipeline
|
|
7
7
|
except ModuleNotFoundError:
|
|
8
|
-
logger.
|
|
8
|
+
logger.warning("docling is not available, might be optional...")
|
|
9
9
|
DOCKING_DEFAULT_ARTIFACTS_PATH, DoclingPipeline = None, None
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
from .marker_ import MarkerPipeline
|
|
13
13
|
except ModuleNotFoundError:
|
|
14
|
-
logger.
|
|
14
|
+
logger.warning("marker is not available, might be optional...")
|
|
15
15
|
MarkerPipeline = None
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
try:
|
|
19
19
|
from .miner_u import MinerUPipeline
|
|
20
20
|
except ModuleNotFoundError:
|
|
21
|
-
logger.
|
|
21
|
+
logger.warning("mineru is not available, might be optional...")
|
|
22
22
|
MinerUPipeline = None
|
|
23
23
|
|
|
24
24
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from icij_common.logging_utils import setup_loggers
|
|
8
|
+
|
|
9
|
+
import extract_python
|
|
10
|
+
|
|
11
|
+
from .doc import configs_app
|
|
12
|
+
from .utils import AsyncTyper
|
|
13
|
+
|
|
14
|
+
cli_app = AsyncTyper(
|
|
15
|
+
context_settings={"help_option_names": ["-h", "--help"]},
|
|
16
|
+
pretty_exceptions_enable=False,
|
|
17
|
+
)
|
|
18
|
+
cli_app.add_typer(configs_app)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def version_callback(value: bool) -> None: # noqa: FBT001
|
|
22
|
+
if value:
|
|
23
|
+
package_version = importlib.metadata.version(extract_python.__name__)
|
|
24
|
+
print(package_version)
|
|
25
|
+
raise typer.Exit()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def pretty_exc_callback(value: bool) -> None: # noqa: FBT001
|
|
29
|
+
if not value:
|
|
30
|
+
os.environ["TYPER_STANDARD_TRACEBACK"] = "1"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@cli_app.callback()
|
|
34
|
+
def main(
|
|
35
|
+
version: Annotated[ # noqa: ARG001
|
|
36
|
+
bool | None,
|
|
37
|
+
typer.Option("--version", callback=version_callback, is_eager=True),
|
|
38
|
+
] = None,
|
|
39
|
+
*,
|
|
40
|
+
pretty_exceptions: Annotated[ # noqa: ARG001
|
|
41
|
+
bool,
|
|
42
|
+
typer.Option(
|
|
43
|
+
"--pretty-exceptions", callback=pretty_exc_callback, is_eager=True
|
|
44
|
+
),
|
|
45
|
+
] = False,
|
|
46
|
+
) -> None:
|
|
47
|
+
setup_loggers(
|
|
48
|
+
["__main__", extract_python.__name__, "docling", "mineru", "marker"],
|
|
49
|
+
level=logging.DEBUG,
|
|
50
|
+
)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated, Never
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from extract_core import (
|
|
8
|
+
Device,
|
|
9
|
+
InputDoc,
|
|
10
|
+
OutputFormat,
|
|
11
|
+
Pipeline,
|
|
12
|
+
PipelineConfig,
|
|
13
|
+
PipelineSize,
|
|
14
|
+
PipelineType,
|
|
15
|
+
)
|
|
16
|
+
from extract_core.default_config import default_config
|
|
17
|
+
from pydantic import TypeAdapter
|
|
18
|
+
|
|
19
|
+
from .utils import AsyncTyper
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
_DOC = "doc"
|
|
24
|
+
|
|
25
|
+
_DOC_CONVERT_HELP = "Converts documents to the provided output format"
|
|
26
|
+
_DOC_CONVERT_DOCS_HELP = "input documents (can be file or directories)"
|
|
27
|
+
_DOC_CONVERT_OUTPUT_PATH_HELP = "directory where the converted documents will be saved"
|
|
28
|
+
_DOC_CONVERT_DEVICE_HELP = "device used to run inference"
|
|
29
|
+
_DOC_CONVERT_OUTPUT_FMT_HELP = "output format"
|
|
30
|
+
_DOC_CONVERT_PIPELINE_CONFIG = "path to a JSON pipeline configuration"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
configs_app = AsyncTyper(name=_DOC)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@configs_app.async_command(help=_DOC_CONVERT_HELP)
|
|
37
|
+
async def convert(
|
|
38
|
+
docs: Annotated[list[Path], typer.Argument(help=_DOC_CONVERT_DOCS_HELP)],
|
|
39
|
+
output_path: Annotated[Path, typer.Argument(help=_DOC_CONVERT_OUTPUT_PATH_HELP)],
|
|
40
|
+
output_format: Annotated[
|
|
41
|
+
OutputFormat, typer.Option(help=_DOC_CONVERT_OUTPUT_FMT_HELP)
|
|
42
|
+
] = OutputFormat.MARKDOWN,
|
|
43
|
+
config: Annotated[
|
|
44
|
+
Path | None,
|
|
45
|
+
typer.Option("-c", "--config", help=_DOC_CONVERT_PIPELINE_CONFIG),
|
|
46
|
+
] = None,
|
|
47
|
+
) -> None:
|
|
48
|
+
if config is not None:
|
|
49
|
+
config = TypeAdapter(PipelineConfig).validate_json(config.read_text())
|
|
50
|
+
else:
|
|
51
|
+
config = default_config(
|
|
52
|
+
pipeline_type=PipelineType.DOCLING,
|
|
53
|
+
device=Device.CPU,
|
|
54
|
+
size=PipelineSize.SMALL,
|
|
55
|
+
)
|
|
56
|
+
config = config.to_device()
|
|
57
|
+
docs = [InputDoc.from_path(d, n_pages=1) for p in docs for d in _walkdir(p)]
|
|
58
|
+
pipeline = Pipeline.from_config(config)
|
|
59
|
+
output_paths = []
|
|
60
|
+
async for res in pipeline.extract_content(docs, output_format, output_path):
|
|
61
|
+
output_path = res.output.path
|
|
62
|
+
logger.info("converted %s to %s", res.input.path, output_path / output_path)
|
|
63
|
+
output_paths.append(output_path / output_path)
|
|
64
|
+
print("\n".join(output_paths))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _raise(exc: OSError) -> Never:
|
|
68
|
+
raise exc
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _walkdir(path: Path) -> list[Path]:
|
|
72
|
+
if path.is_file():
|
|
73
|
+
return [path]
|
|
74
|
+
paths = []
|
|
75
|
+
for root, _, files in os.walk(path, onerror=_raise):
|
|
76
|
+
root = Path(root) # noqa: PLW2901
|
|
77
|
+
paths.extend(root / f for f in files)
|
|
78
|
+
return paths
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import sys
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from functools import wraps
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncTyper(typer.Typer):
|
|
11
|
+
def async_command(self, *args, **kwargs) -> Callable[[Callable], Callable]:
|
|
12
|
+
def decorator(async_func: Callable) -> Callable:
|
|
13
|
+
@wraps(async_func)
|
|
14
|
+
def sync_func(*_args, **_kwargs) -> Any:
|
|
15
|
+
res = asyncio.run(async_func(*_args, **_kwargs))
|
|
16
|
+
return res
|
|
17
|
+
|
|
18
|
+
self.command(*args, **kwargs)(sync_func)
|
|
19
|
+
return async_func
|
|
20
|
+
|
|
21
|
+
return decorator
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def eprint(*args, **kwargs) -> None:
|
|
25
|
+
print(*args, file=sys.stderr, **kwargs)
|
extract_python/docling_.py
CHANGED
|
@@ -59,8 +59,7 @@ class DoclingPipeline(Pipeline):
|
|
|
59
59
|
def __init__(self, config: DoclingPipelineConfig):
|
|
60
60
|
super().__init__(config)
|
|
61
61
|
format_options = {
|
|
62
|
-
k: v.to_docling(self.
|
|
63
|
-
for k, v in self._config.format_options.items()
|
|
62
|
+
k: v.to_docling() for k, v in self._config.format_options.items()
|
|
64
63
|
}
|
|
65
64
|
logger.info(
|
|
66
65
|
"resolved format options to: %s",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: extract-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.1
|
|
4
4
|
Summary: Structured content extraction
|
|
5
5
|
Project-URL: Homepage, https://github.com/ICIJ/extract-python
|
|
6
6
|
Project-URL: Repository, https://github.com/ICIJ/extract-python
|
|
7
7
|
Project-URL: Issues, https://github.com/ICIJ/extract-python/issues
|
|
8
8
|
Author-email: Clément Doumouro <cdoumouro@icij.org>
|
|
9
9
|
Requires-Python: <3.15,>=3.13
|
|
10
|
-
Requires-Dist: extract-core~=0.
|
|
10
|
+
Requires-Dist: extract-core~=0.11.0
|
|
11
11
|
Requires-Dist: icij-common~=0.8.2
|
|
12
12
|
Requires-Dist: pympler~=1.1
|
|
13
13
|
Provides-Extra: benches
|
|
@@ -15,6 +15,8 @@ Requires-Dist: html2image~=2.0.7; extra == 'benches'
|
|
|
15
15
|
Requires-Dist: markdown2>=2.5.4; extra == 'benches'
|
|
16
16
|
Requires-Dist: notebook>=7.4.5; extra == 'benches'
|
|
17
17
|
Requires-Dist: pypdfium2>=4.30.0; extra == 'benches'
|
|
18
|
+
Provides-Extra: cli
|
|
19
|
+
Requires-Dist: typer~=0.21.2; extra == 'cli'
|
|
18
20
|
Provides-Extra: docling
|
|
19
21
|
Requires-Dist: docling-slim[feat-ocr-easyocr,feat-ocr-mac,feat-ocr-rapidocr,feat-ocr-tesserocr,standard]~=2.127; extra == 'docling'
|
|
20
22
|
Provides-Extra: docling-gpu
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
extract_python/__init__.py,sha256=mUWwAYj8dRhM79J_Ns_yNM3WG2GDqWRNXZd3XVkkUaY,753
|
|
2
|
+
extract_python/__main__.py,sha256=g-fvS46zl9umKmGrSpl-OG-8PSuZgjqvTCqjpsZtSps,101
|
|
3
|
+
extract_python/constants.py,sha256=659V40LcTWJhX3IbuJLSSvI5AsGJh9ciMrGCfzJn2zA,98
|
|
4
|
+
extract_python/docling_.py,sha256=iZha9zh6uyFo67RVB0YqHMJt9auzJJV0kJ1OCPTOan8,10030
|
|
5
|
+
extract_python/marker_.py,sha256=bb0DJXrSWOznIuPnw4-adR5_R9QiwtFGGBh5KlXFxjM,3323
|
|
6
|
+
extract_python/miner_u.py,sha256=sEU1PhPpfPVo4jP7flNlbGO9PfsLFLz973-ufZEd0ws,3966
|
|
7
|
+
extract_python/utils.py,sha256=LrR1tlOgpWEri6TLDlYYPRBmlka-AjOepWnbySf2Haw,9974
|
|
8
|
+
extract_python/cli/__init__.py,sha256=Xt3MB74fO8cimm0Xas8dIMmXu62O0dV-4o3-OUzZggo,1245
|
|
9
|
+
extract_python/cli/doc.py,sha256=SMwRs-7-u_lw3wpHO6m3vFYnbjYCn_qIVC-q2TIxcbg,2435
|
|
10
|
+
extract_python/cli/utils.py,sha256=Png7oGKKxDeStn27k-o4Hxlzl-G-u-QDSH6IfJqUk1I,667
|
|
11
|
+
extract_python-0.11.1.dist-info/METADATA,sha256=B4sG_uDFLruPQE3ytKMq5o7ODQOKGRlYGgvyuFiBmkE,1429
|
|
12
|
+
extract_python-0.11.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
13
|
+
extract_python-0.11.1.dist-info/entry_points.txt,sha256=noSkCWA0LRm0V7WbmYDPBnJrKeiYdpvXynAW6y72Z4M,64
|
|
14
|
+
extract_python-0.11.1.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
extract_python/__init__.py,sha256=DA2LUro6vMjfS8fb2MsqO95FbJEZHyZ7kFyn42q02Wk,759
|
|
2
|
-
extract_python/constants.py,sha256=659V40LcTWJhX3IbuJLSSvI5AsGJh9ciMrGCfzJn2zA,98
|
|
3
|
-
extract_python/docling_.py,sha256=zD5rIXV1pAQBNGZc0RliP9buHjttz4CdSOj21Z4FbFo,10054
|
|
4
|
-
extract_python/marker_.py,sha256=bb0DJXrSWOznIuPnw4-adR5_R9QiwtFGGBh5KlXFxjM,3323
|
|
5
|
-
extract_python/miner_u.py,sha256=sEU1PhPpfPVo4jP7flNlbGO9PfsLFLz973-ufZEd0ws,3966
|
|
6
|
-
extract_python/utils.py,sha256=LrR1tlOgpWEri6TLDlYYPRBmlka-AjOepWnbySf2Haw,9974
|
|
7
|
-
extract_python-0.10.4.dist-info/METADATA,sha256=5UcF7UU0SgfLmsb-oSXbCfZWzUBOKSYSvZFUILttM4o,1364
|
|
8
|
-
extract_python-0.10.4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
9
|
-
extract_python-0.10.4.dist-info/RECORD,,
|
|
File without changes
|