Skip to content

Commit 706fef8

Browse files
authored
Merge pull request #13 from ArchiveBox/claude/add-liteparse-plugin-d7Awc
Add LiteParse plugin for PDF text extraction
2 parents 984e9db + a36840f commit 706fef8

14 files changed

Lines changed: 765 additions & 599 deletions

File tree

abx_plugins/plugins/defuddle/tests/test_defuddle.py

Lines changed: 9 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import subprocess
44
import sys
55
import tempfile
6-
import uuid
76
from pathlib import Path
87
from urllib.request import urlopen
98

@@ -31,7 +30,6 @@
3130

3231
TEST_URL = "https://example.com"
3332
_defuddle_binary_path = None
34-
_defuddle_lib_root = None
3533

3634

3735
def create_example_html(tmpdir: Path) -> Path:
@@ -58,91 +56,21 @@ def require_defuddle_binary() -> str:
5856

5957

6058
def get_defuddle_binary_path() -> str | None:
61-
"""Get defuddle path from cache or by running install hooks."""
59+
"""Get defuddle binary path, installing via abx_pkg if needed."""
6260
global _defuddle_binary_path
6361
if _defuddle_binary_path and Path(_defuddle_binary_path).is_file():
6462
return _defuddle_binary_path
6563

6664
from abx_pkg import Binary, EnvProvider, NpmProvider
6765

68-
try:
69-
binary = Binary(
70-
name="defuddle",
71-
binproviders=[NpmProvider(), EnvProvider()],
72-
overrides={"npm": {"install_args": ["defuddle"]}},
73-
).load()
74-
if binary and binary.abspath:
75-
_defuddle_binary_path = str(binary.abspath)
76-
return _defuddle_binary_path
77-
except Exception:
78-
pass
79-
80-
npm_hook = PLUGINS_ROOT / "npm" / "on_Binary__10_npm_install.py"
81-
if not npm_hook.exists():
82-
return None
83-
84-
binary_id = str(uuid.uuid4())
85-
machine_id = str(uuid.uuid4())
86-
binproviders = "*"
87-
overrides = None
88-
89-
crawl_result = subprocess.run(
90-
[str(DEFUDDLE_CRAWL_HOOK)],
91-
capture_output=True,
92-
text=True,
93-
timeout=30,
94-
)
95-
for line in crawl_result.stdout.strip().split("\n"):
96-
if not line.strip().startswith("{"):
97-
continue
98-
try:
99-
record = json.loads(line)
100-
except json.JSONDecodeError:
101-
continue
102-
if record.get("type") == "Binary" and record.get("name") == "defuddle":
103-
binproviders = record.get("binproviders", "*")
104-
overrides = record.get("overrides")
105-
break
106-
107-
global _defuddle_lib_root
108-
if not _defuddle_lib_root:
109-
_defuddle_lib_root = tempfile.mkdtemp(prefix="defuddle-lib-")
110-
111-
env = os.environ.copy()
112-
env["LIB_DIR"] = str(Path(_defuddle_lib_root) / ".config" / "abx" / "lib")
113-
env["SNAP_DIR"] = str(Path(_defuddle_lib_root) / "data")
114-
env["CRAWL_DIR"] = str(Path(_defuddle_lib_root) / "crawl")
115-
116-
cmd = [str(npm_hook),
117-
"--binary-id",
118-
binary_id,
119-
"--machine-id",
120-
machine_id,
121-
"--name",
122-
"defuddle",
123-
f"--binproviders={binproviders}",
124-
]
125-
if overrides:
126-
cmd.append(f"--overrides={json.dumps(overrides)}")
127-
128-
install_result = subprocess.run(
129-
cmd,
130-
capture_output=True,
131-
text=True,
132-
timeout=300,
133-
env=env,
134-
)
135-
136-
for line in install_result.stdout.strip().split("\n"):
137-
if not line.strip().startswith("{"):
138-
continue
139-
try:
140-
record = json.loads(line)
141-
except json.JSONDecodeError:
142-
continue
143-
if record.get("type") == "Binary" and record.get("name") == "defuddle":
144-
_defuddle_binary_path = record.get("abspath")
145-
return _defuddle_binary_path
66+
binary = Binary(
67+
name="defuddle",
68+
binproviders=[NpmProvider(), EnvProvider()],
69+
overrides={"npm": {"install_args": ["defuddle"]}},
70+
).load_or_install()
71+
if binary and binary.abspath:
72+
_defuddle_binary_path = str(binary.abspath)
73+
return _defuddle_binary_path
14674

14775
return None
14876

abx_plugins/plugins/forumdl/tests/test_forumdl.py

Lines changed: 29 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import sys
1919
import tempfile
2020
import time
21-
import uuid
2221
from pathlib import Path
2322
import pytest
2423

@@ -35,7 +34,6 @@
3534

3635
# Module-level cache for binary path
3736
_forumdl_binary_path = None
38-
_forumdl_lib_root = None
3937

4038

4139
def require_forumdl_binary() -> str:
@@ -49,95 +47,41 @@ def require_forumdl_binary() -> str:
4947
return binary_path
5048

5149

52-
def get_forumdl_binary_path():
53-
"""Get the installed forum-dl binary path from cache or by running installation."""
50+
def get_forumdl_binary_path() -> str | None:
51+
"""Get forum-dl binary path, installing via abx_pkg if needed."""
5452
global _forumdl_binary_path
5553
if _forumdl_binary_path:
5654
return _forumdl_binary_path
5755

58-
# Try to find forum-dl binary using abx-pkg
5956
from abx_pkg import Binary, PipProvider, EnvProvider
6057

61-
try:
62-
binary = Binary(
63-
name="forum-dl", binproviders=[PipProvider(), EnvProvider()]
64-
).load()
65-
66-
if binary and binary.abspath:
67-
_forumdl_binary_path = str(binary.abspath)
68-
return _forumdl_binary_path
69-
except Exception:
70-
pass
71-
72-
# If not found, try to install via pip using the crawl hook overrides
73-
pip_hook = PLUGINS_ROOT / "pip" / "on_Binary__11_pip_install.py"
74-
crawl_hook = next(PLUGIN_DIR.glob("on_Crawl__25_forumdl_install*.py"), None)
75-
if pip_hook.exists():
76-
binary_id = str(uuid.uuid4())
77-
machine_id = str(uuid.uuid4())
78-
overrides = None
79-
80-
if crawl_hook and crawl_hook.exists():
81-
crawl_result = subprocess.run(
82-
[str(crawl_hook)],
83-
capture_output=True,
84-
text=True,
85-
timeout=30,
86-
)
87-
for crawl_line in crawl_result.stdout.strip().split("\n"):
88-
if crawl_line.strip().startswith("{"):
89-
try:
90-
crawl_record = json.loads(crawl_line)
91-
if (
92-
crawl_record.get("type") == "Binary"
93-
and crawl_record.get("name") == "forum-dl"
94-
):
95-
overrides = crawl_record.get("overrides")
96-
break
97-
except json.JSONDecodeError:
98-
continue
99-
100-
# Create a persistent temp HOME for default LIB_DIR usage
101-
global _forumdl_lib_root
102-
if not _forumdl_lib_root:
103-
_forumdl_lib_root = tempfile.mkdtemp(prefix="forumdl-lib-")
104-
env = os.environ.copy()
105-
env["HOME"] = str(_forumdl_lib_root)
106-
env["SNAP_DIR"] = str(Path(_forumdl_lib_root) / "data")
107-
env.pop("LIB_DIR", None)
108-
109-
cmd = [str(pip_hook),
110-
"--binary-id",
111-
binary_id,
112-
"--machine-id",
113-
machine_id,
114-
"--name",
115-
"forum-dl",
116-
]
117-
if overrides:
118-
cmd.append(f"--overrides={json.dumps(overrides)}")
119-
120-
install_result = subprocess.run(
121-
cmd,
122-
capture_output=True,
123-
text=True,
124-
timeout=300,
125-
env=env,
126-
)
127-
128-
# Parse Binary from pip installation
129-
for install_line in install_result.stdout.strip().split("\n"):
130-
if install_line.strip():
131-
try:
132-
install_record = json.loads(install_line)
133-
if (
134-
install_record.get("type") == "Binary"
135-
and install_record.get("name") == "forum-dl"
136-
):
137-
_forumdl_binary_path = install_record.get("abspath")
138-
return _forumdl_binary_path
139-
except json.JSONDecodeError:
140-
pass
58+
binary = Binary(
59+
name="forum-dl",
60+
binproviders=[PipProvider(), EnvProvider()],
61+
overrides={
62+
"pip": {
63+
"install_args": [
64+
"--no-deps",
65+
"--prefer-binary",
66+
"forum-dl",
67+
"chardet==5.2.0",
68+
"beautifulsoup4",
69+
"soupsieve",
70+
"lxml",
71+
"requests",
72+
"urllib3",
73+
"tenacity",
74+
"python-dateutil",
75+
"six",
76+
"html2text",
77+
"warcio",
78+
]
79+
}
80+
},
81+
).load_or_install()
82+
if binary and binary.abspath:
83+
_forumdl_binary_path = str(binary.abspath)
84+
return _forumdl_binary_path
14185

14286
return None
14387

abx_plugins/plugins/gallerydl/tests/test_gallerydl.py

Lines changed: 9 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import tempfile
1919
import time
2020
import os
21-
import uuid
2221
from pathlib import Path
2322
import pytest
2423

@@ -35,7 +34,6 @@
3534

3635
# Module-level cache for binary path
3736
_gallerydl_binary_path = None
38-
_gallerydl_lib_root = None
3937

4038

4139
def require_gallerydl_binary() -> str:
@@ -49,91 +47,21 @@ def require_gallerydl_binary() -> str:
4947
return binary_path
5048

5149

52-
def get_gallerydl_binary_path():
53-
"""Get gallery-dl binary path from cache or by running install hooks."""
50+
def get_gallerydl_binary_path() -> str | None:
51+
"""Get gallery-dl binary path, installing via abx_pkg if needed."""
5452
global _gallerydl_binary_path
5553
if _gallerydl_binary_path and Path(_gallerydl_binary_path).is_file():
5654
return _gallerydl_binary_path
5755

58-
# Try loading from existing providers first
5956
from abx_pkg import Binary, PipProvider, EnvProvider
6057

61-
try:
62-
binary = Binary(
63-
name="gallery-dl", binproviders=[PipProvider(), EnvProvider()]
64-
).load()
65-
if binary and binary.abspath:
66-
_gallerydl_binary_path = str(binary.abspath)
67-
return _gallerydl_binary_path
68-
except Exception:
69-
pass
70-
71-
# Install via real plugin hooks
72-
pip_hook = PLUGINS_ROOT / "pip" / "on_Binary__11_pip_install.py"
73-
crawl_hook = next(PLUGIN_DIR.glob("on_Crawl__20_gallerydl_install*.py"), None)
74-
if not pip_hook.exists():
75-
return None
76-
77-
binary_id = str(uuid.uuid4())
78-
machine_id = str(uuid.uuid4())
79-
overrides = None
80-
81-
if crawl_hook and crawl_hook.exists():
82-
crawl_result = subprocess.run(
83-
[str(crawl_hook)],
84-
capture_output=True,
85-
text=True,
86-
timeout=30,
87-
)
88-
for line in crawl_result.stdout.strip().split("\n"):
89-
if not line.strip().startswith("{"):
90-
continue
91-
try:
92-
record = json.loads(line)
93-
except json.JSONDecodeError:
94-
continue
95-
if record.get("type") == "Binary" and record.get("name") == "gallery-dl":
96-
overrides = record.get("overrides")
97-
break
98-
99-
global _gallerydl_lib_root
100-
if not _gallerydl_lib_root:
101-
_gallerydl_lib_root = tempfile.mkdtemp(prefix="gallerydl-lib-")
102-
103-
env = os.environ.copy()
104-
env["HOME"] = str(_gallerydl_lib_root)
105-
env["SNAP_DIR"] = str(Path(_gallerydl_lib_root) / "data")
106-
env.pop("LIB_DIR", None)
107-
108-
cmd = [str(pip_hook),
109-
"--binary-id",
110-
binary_id,
111-
"--machine-id",
112-
machine_id,
113-
"--name",
114-
"gallery-dl",
115-
]
116-
if overrides:
117-
cmd.append(f"--overrides={json.dumps(overrides)}")
118-
119-
install_result = subprocess.run(
120-
cmd,
121-
capture_output=True,
122-
text=True,
123-
timeout=300,
124-
env=env,
125-
)
126-
127-
for line in install_result.stdout.strip().split("\n"):
128-
if not line.strip().startswith("{"):
129-
continue
130-
try:
131-
record = json.loads(line)
132-
except json.JSONDecodeError:
133-
continue
134-
if record.get("type") == "Binary" and record.get("name") == "gallery-dl":
135-
_gallerydl_binary_path = record.get("abspath")
136-
return _gallerydl_binary_path
58+
binary = Binary(
59+
name="gallery-dl",
60+
binproviders=[PipProvider(), EnvProvider()],
61+
).load_or_install()
62+
if binary and binary.abspath:
63+
_gallerydl_binary_path = str(binary.abspath)
64+
return _gallerydl_binary_path
13765

13866
return None
13967

abx_plugins/plugins/liteparse/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)