scraper-rust 0.4.3__tar.gz → 0.5.0__tar.gz

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.
Files changed (52) hide show
  1. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/.gitignore +1 -0
  2. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/AGENTS.md +41 -24
  3. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/Cargo.lock +113 -193
  4. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/Cargo.toml +3 -3
  5. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/PKG-INFO +6 -5
  6. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/README.md +5 -4
  7. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/benchmarks/README.md +9 -13
  8. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/README.md +4 -3
  9. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/api.md +12 -9
  10. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/architecture.md +13 -12
  11. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/async-api.md +3 -3
  12. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/development.md +5 -4
  13. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/docs/limits-and-errors.md +7 -7
  14. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/pyproject.toml +1 -1
  15. scraper_rust-0.5.0/src/async_core.rs +304 -0
  16. scraper_rust-0.5.0/src/cache.rs +42 -0
  17. scraper_rust-0.5.0/src/document.rs +275 -0
  18. scraper_rust-0.5.0/src/element.rs +208 -0
  19. scraper_rust-0.5.0/src/functions.rs +249 -0
  20. scraper_rust-0.5.0/src/html5_dict.rs +493 -0
  21. scraper_rust-0.5.0/src/lib.rs +66 -0
  22. scraper_rust-0.5.0/src/limits.rs +30 -0
  23. scraper_rust-0.5.0/src/prettify.rs +207 -0
  24. scraper_rust-0.5.0/src/runtime.rs +27 -0
  25. scraper_rust-0.5.0/src/selectors.rs +85 -0
  26. scraper_rust-0.5.0/src/tests.rs +462 -0
  27. scraper_rust-0.5.0/src/text.rs +76 -0
  28. scraper_rust-0.5.0/src/xpath.rs +249 -0
  29. scraper_rust-0.5.0/uv.lock +247 -0
  30. scraper_rust-0.4.3/src/lib.rs +0 -2610
  31. scraper_rust-0.4.3/uv.lock +0 -247
  32. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/.github/workflows/benchmark.yml +0 -0
  33. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/.github/workflows/bump-version.yml +0 -0
  34. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/.github/workflows/release.yml +0 -0
  35. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/.github/workflows/tests.yml +0 -0
  36. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/LICENSE +0 -0
  37. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/benchmarks/bench_parse_memory.py +0 -0
  38. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/benchmarks/bench_sync_async.py +0 -0
  39. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/benchmarks/bench_vs_markupever.py +0 -0
  40. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/examples/demo.py +0 -0
  41. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/examples/demo_async_document.py +0 -0
  42. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/examples/demo_asyncio.py +0 -0
  43. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/examples/demo_prettify_url.py +0 -0
  44. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/justfile +0 -0
  45. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/py.typed +0 -0
  46. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/scraper_rs/__init__.py +0 -0
  47. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/scraper_rs/asyncio.py +0 -0
  48. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/scraper_rs/asyncio.pyi +0 -0
  49. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/scraper_rs.pyi +0 -0
  50. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/tests/test_asyncio.py +0 -0
  51. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/tests/test_performance.py +0 -0
  52. {scraper_rust-0.4.3 → scraper_rust-0.5.0}/tests/test_scraper.py +0 -0
@@ -23,6 +23,7 @@ env/
23
23
  .ruff_cache/
24
24
  .pytest_cache/
25
25
  .hypothesis/
26
+ .uv-cache/
26
27
  .coverage
27
28
  .coverage.*
28
29
  htmlcov/
@@ -17,10 +17,11 @@ This file contains essential information for Large Language Models (LLMs) to eff
17
17
 
18
18
  ### Core Technologies
19
19
  - **Rust** (2024 edition)
20
- - `scraper` v0.25 - HTML parsing and CSS selection
20
+ - `scraper` v0.27.0 from `rust-scraper/scraper` with the `atomic` feature - HTML parsing and CSS selection
21
21
  - `xee-xpath` v0.1.5 - XPath support
22
- - `pyo3` v0.27 with `extension-module` and `abi3-py310` features
23
- - `pyo3-async-runtimes` v0.27 with `tokio-runtime` feature
22
+ - `html5ever` v0.39.0 - parse-tree dictionary helpers
23
+ - `pyo3` v0.28.3 with `abi3-py310`; the `extension-module` feature is enabled through the package build config
24
+ - `pyo3-async-runtimes` v0.28 with `tokio-runtime` feature
24
25
  - `tokio` v1 (rt, macros) for async wrappers
25
26
  - **Python** 3.10+
26
27
  - Type annotations and stub files (`scraper_rs.pyi`, `py.typed`)
@@ -40,13 +41,25 @@ This file contains essential information for Large Language Models (LLMs) to eff
40
41
  ```
41
42
  scraper-rs/
42
43
  ├── src/
43
- └── lib.rs # Main Rust source (PyO3 bindings)
44
+ ├── lib.rs # PyO3 module entry point
45
+ │ ├── document.rs # Document class
46
+ │ ├── element.rs # Element class and snapshots
47
+ │ ├── functions.rs # Top-level functions
48
+ │ ├── selectors.rs # CSS selector helpers/cache
49
+ │ ├── xpath.rs # XPath helpers/cache
50
+ │ ├── limits.rs # Size limits and truncation
51
+ │ ├── prettify.rs # Pretty-print helpers
52
+ │ ├── html5_dict.rs # parse_document/parse_fragment dictionaries
53
+ │ └── async_core.rs # Extension-level async core helpers
44
54
  ├── tests/
45
55
  │ ├── test_scraper.py # Synchronous API tests
46
- └── test_asyncio.py # Asynchronous API tests
56
+ ├── test_asyncio.py # Asynchronous API tests
57
+ │ └── test_performance.py # Performance behavior tests
47
58
  ├── examples/
48
59
  │ ├── demo.py # Sync usage examples
49
- └── demo_asyncio.py # Async usage examples
60
+ ├── demo_asyncio.py # Async usage examples
61
+ │ ├── demo_async_document.py
62
+ │ └── demo_prettify_url.py
50
63
  ├── scraper_rs/ # Python package directory (async wrappers + import glue)
51
64
  ├── scraper_rs.pyi # Type stub file
52
65
  ├── py.typed # PEP 561 marker for type support
@@ -59,18 +72,17 @@ scraper-rs/
59
72
 
60
73
  ### Key Files
61
74
 
62
- - **`src/lib.rs`**: Single Rust source file containing all PyO3 bindings
63
- - `Document` class: Main HTML document wrapper
64
- - `Element` class: Snapshot of HTML element with tag, text, HTML, and attributes
65
- - Helper functions: `parse()`, `select()`, `select_first()`, `first()`, `xpath()`, `xpath_first()`
66
- - Size limit enforcement (default 1 GiB, configurable via `max_size_bytes`)
67
- - Truncation support (`truncate_on_limit` parameter)
75
+ - **`src/lib.rs`**: PyO3 module initializer that registers classes, helper functions, metadata, and extension-level async helpers
76
+ - **`src/document.rs`**: `Document` class and persistent DOM/XPath state
77
+ - **`src/element.rs`**: `Element` class, owned element snapshots, lazy field computation
78
+ - **`src/functions.rs`**: Top-level helpers: `parse()`, `parse_document()`, `parse_fragment()`, `prettify()`, `select()`, `select_first()`, `first()`, `xpath()`, `xpath_first()`
79
+ - **`src/selectors.rs`**, **`src/xpath.rs`**, **`src/limits.rs`**: selector caches, XPath conversion, size limit enforcement, and UTF-8-safe truncation
68
80
 
69
81
  - **`scraper_rs.pyi`**: Type stubs for IDE support and type checking
70
82
 
71
83
  - **`Cargo.toml`**: Rust crate configuration
72
84
  - `crate-type = ["cdylib"]` for Python extension module
73
- - Release optimizations: LTO, `codegen-units = 1`, `opt-level = "z"`
85
+ - Release optimizations: fat LTO, `codegen-units = 1`, `opt-level = 3`, `panic = "abort"`, `strip = true`
74
86
 
75
87
  - **`pyproject.toml`**: Python package metadata and build configuration
76
88
  - Maturin build backend
@@ -170,7 +182,7 @@ pytest tests/ -v
170
182
  ### CI/CD
171
183
  - **GitHub Actions**: `.github/workflows/tests.yml`
172
184
  - Runs on Ubuntu latest
173
- - Tests against Python 3.10, 3.11, 3.12, 3.13, 3.14
185
+ - Tests against Python 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t
174
186
  - Steps: checkout → setup Python/Rust → install deps → build with maturin → run pytest
175
187
 
176
188
  ## API Design
@@ -201,6 +213,9 @@ pytest tests/ -v
201
213
 
202
214
  ### Top-Level Functions
203
215
  - `parse(html, max_size_bytes, truncate_on_limit) -> Document`
216
+ - `parse_document(html, max_size_bytes, truncate_on_limit) -> dict`
217
+ - `parse_fragment(html, max_size_bytes, truncate_on_limit) -> dict`
218
+ - `prettify(html, max_size_bytes, truncate_on_limit) -> str`
204
219
  - `select(html, css, max_size_bytes, truncate_on_limit) -> list[Element]`
205
220
  - `select_first(html, css, max_size_bytes, truncate_on_limit) -> Element | None`
206
221
  - `first(html, css, max_size_bytes, truncate_on_limit) -> Element | None`
@@ -211,12 +226,12 @@ pytest tests/ -v
211
226
  Module: `scraper_rs.asyncio`
212
227
  - `AsyncDocument` and `AsyncElement` wrappers mirror the sync API
213
228
  - `parse()` yields to the event loop once before constructing the document
214
- - `select()` and `xpath()` run in a thread pool via `pyo3-async-runtimes` + `tokio::task::spawn_blocking`
229
+ - The public `scraper_rs.asyncio` Python wrappers yield once and then call the sync helpers. They provide coroutine API consistency, but do not make CPU-bound parsing parallel on their own.
215
230
  - Same keyword arguments as sync versions
216
231
 
217
232
  ## Code Conventions
218
233
 
219
- ### Rust Code (`src/lib.rs`)
234
+ ### Rust Code (`src/`)
220
235
  - Use `#[pyclass]` for Python-exposed classes
221
236
  - Use `#[pymethods]` for Python-exposed methods
222
237
  - Use `#[getter]` for property accessors
@@ -242,7 +257,7 @@ Module: `scraper_rs.asyncio`
242
257
  ## Common Development Tasks
243
258
 
244
259
  ### Adding a New Method to Document
245
- 1. Add Rust implementation in `src/lib.rs` under `impl Document`
260
+ 1. Add Rust implementation in `src/document.rs` under `impl Document`
246
261
  2. Add `#[pymethods]` annotation if needed
247
262
  3. Update `scraper_rs.pyi` with type signature
248
263
  4. Add tests in `tests/test_scraper.py`
@@ -252,7 +267,7 @@ Module: `scraper_rs.asyncio`
252
267
  8. Run `pytest tests/` to verify
253
268
 
254
269
  ### Adding a New Top-Level Function
255
- 1. Add Rust function in `src/lib.rs` with `#[pyfunction]`
270
+ 1. Add Rust function in `src/functions.rs` with `#[pyfunction]`
256
271
  2. Register with `m.add_function(wrap_pyfunction!(function_name, m)?)?` in `scraper_rs` module
257
272
  3. Export in `__all__` if applicable
258
273
  4. Update `scraper_rs.pyi`
@@ -270,7 +285,8 @@ Module: `scraper_rs.asyncio`
270
285
  ### Release Process
271
286
  See `.github/workflows/release.yml` and `.github/workflows/bump-version.yml`
272
287
  - Version is specified in both `Cargo.toml` and `pyproject.toml` (must match)
273
- - Manylinux wheels built via Docker with official maturin image
288
+ - Release workflow builds abi3 wheels for Linux, Windows, and macOS, plus free-threaded wheels for Python 3.13t and 3.14t
289
+ - Local manylinux builds are available via Docker with `just build_manylinux`
274
290
  - Published to PyPI via `maturin publish`
275
291
 
276
292
  ## Important Notes for LLMs
@@ -279,8 +295,8 @@ See `.github/workflows/release.yml` and `.github/workflows/bump-version.yml`
279
295
  2. **PyO3 limitations**: Not all Rust types can cross the FFI boundary - use owned data
280
296
  3. **Size limits**: Always respect `max_size_bytes` to prevent memory issues
281
297
  4. **UTF-8 safety**: Truncation must respect character boundaries
282
- 5. **Async wrappers**: Rust exposes async helpers via `pyo3-async-runtimes` + `tokio::task::spawn_blocking`; parsing/selectors remain synchronous
283
- 6. **Single source file**: All Rust code is in `src/lib.rs` (keep it organized)
298
+ 5. **Async wrappers**: Public async wrappers live in `scraper_rs/asyncio.py`; keep their stubs and tests aligned with sync behavior
299
+ 6. **Rust modules are split by responsibility**: `src/lib.rs` is the module entry point; add core behavior to the focused module that owns it
284
300
  7. **Type stubs are critical**: Always update `scraper_rs.pyi` when changing APIs
285
301
  8. **Tests are comprehensive**: Follow existing test patterns in `tests/`
286
302
  9. **Build artifacts**: `target/` and `.venv/` should not be committed
@@ -289,11 +305,12 @@ See `.github/workflows/release.yml` and `.github/workflows/bump-version.yml`
289
305
  ## Dependencies
290
306
 
291
307
  ### Rust Dependencies (Cargo.toml)
292
- - `pyo3 = { version = "0.27", features = ["extension-module", "abi3-py310"] }`
293
- - `pyo3-async-runtimes = { version = "0.27", features = ["tokio-runtime"] }`
308
+ - `pyo3 = { version = "0.28.3", features = ["abi3-py310"] }`
309
+ - `pyo3-async-runtimes = { version = "0.28", features = ["tokio-runtime"] }`
294
310
  - `tokio = { version = "1", features = ["rt", "macros"] }`
295
- - `scraper = "0.25"`
311
+ - `scraper = { version = "0.27.0", git = "https://github.com/rust-scraper/scraper", features = ["atomic"], rev = "9c1eff304e45a8bccb463968268ce6758703e821" }`
296
312
  - `xee-xpath = "0.1.5"`
313
+ - `html5ever = "0.39.0"`
297
314
 
298
315
  ### Python Dependencies (pyproject.toml)
299
316
  **Runtime**: None (self-contained binary wheel)