feedparser-rs 0.7.2__cp315-cp315-win_amd64.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.
@@ -0,0 +1,39 @@
1
+ """
2
+ feedparser_rs: High-performance RSS/Atom/JSON Feed parser
3
+
4
+ Drop-in replacement for Python's feedparser library with 10-100x performance.
5
+ Written in Rust with PyO3 bindings for maximum speed and safety.
6
+
7
+ Usage:
8
+ >>> import feedparser_rs
9
+ >>> d = feedparser_rs.parse('<rss>...</rss>')
10
+ >>> print(d.feed.title)
11
+ >>> print(d.entries[0].published_parsed)
12
+
13
+ For full documentation, see: https://github.com/bug-ops/feedparser-rs
14
+ """
15
+
16
+ from ._feedparser_rs import (
17
+ FeedParserDict,
18
+ ParserLimits,
19
+ __version__,
20
+ detect_format,
21
+ parse,
22
+ parse_url,
23
+ parse_url_with_limits,
24
+ parse_with_limits,
25
+ )
26
+
27
+ __all__ = [
28
+ "FeedParserDict",
29
+ "ParserLimits",
30
+ "__version__",
31
+ "detect_format",
32
+ "parse",
33
+ "parse_url",
34
+ "parse_url_with_limits",
35
+ "parse_with_limits",
36
+ ]
37
+
38
+ # Type alias for better IDE support
39
+ ParseResult = FeedParserDict
feedparser_rs/py.typed ADDED
@@ -0,0 +1 @@
1
+ # PEP 561 marker for type checking
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: feedparser-rs
3
+ Version: 0.7.2
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: License :: OSI Approved :: Apache Software License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Rust
14
+ Classifier: Topic :: Text Processing :: Markup :: XML
15
+ Summary: High-performance RSS/Atom/JSON Feed parser with feedparser-compatible API
16
+ Keywords: rss,atom,feed,parser,feedparser,rust
17
+ License: MIT OR Apache-2.0
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
20
+ Project-URL: Documentation, https://github.com/bug-ops/feedparser-rs#readme
21
+ Project-URL: Homepage, https://github.com/bug-ops/feedparser-rs
22
+ Project-URL: Repository, https://github.com/bug-ops/feedparser-rs
23
+
24
+ # feedparser-rs
25
+
26
+ [![PyPI](https://img.shields.io/pypi/v/feedparser-rs)](https://pypi.org/project/feedparser-rs/)
27
+ [![Python](https://img.shields.io/pypi/pyversions/feedparser-rs)](https://pypi.org/project/feedparser-rs/)
28
+ [![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue)](LICENSE-MIT)
29
+
30
+ High-performance RSS/Atom/JSON Feed parser for Python with feedparser-compatible API.
31
+
32
+ ## Features
33
+
34
+ - **Fast**: Native Rust implementation via PyO3
35
+ - **HTTP fetching**: Built-in URL fetching with compression (gzip, deflate, brotli)
36
+ - **Conditional GET**: ETag/Last-Modified support for efficient polling
37
+ - **Tolerant parsing**: Bozo flag for graceful handling of malformed feeds
38
+ - **Sanitized by default**: HTML-bearing fields are sanitized against XSS unless explicitly disabled via `sanitize_html=False`
39
+ - **Multi-format**: RSS 0.9x/1.0/2.0, Atom 0.3/1.0, JSON Feed 1.0/1.1
40
+ - **Podcast support**: iTunes and Podcast 2.0 namespace extensions
41
+ - **JSON Feed extensions**: `_`-prefixed custom objects (e.g. `_cast`) captured as `feed.json_extensions`/`entry.json_extensions` dicts
42
+ - **feedparser-compatible**: Dict-style access, field aliases, same API patterns
43
+ - **DoS protection**: Built-in resource limits
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install feedparser-rs
49
+ ```
50
+
51
+ > **Important:** Requires Python 3.10 or later.
52
+
53
+ ## Usage
54
+
55
+ ### Basic Parsing
56
+
57
+ ```python
58
+ import feedparser_rs
59
+
60
+ # Parse from string, bytes, or URL (auto-detected)
61
+ d = feedparser_rs.parse("<rss>...</rss>")
62
+ d = feedparser_rs.parse(b"<rss>...</rss>")
63
+ d = feedparser_rs.parse("https://example.com/feed.xml") # URL auto-detected
64
+
65
+ # Attribute-style access (feedparser-compatible)
66
+ print(d.feed.title)
67
+ print(d.version) # "rss20", "atom10", etc.
68
+ print(d.bozo) # True if parsing errors occurred
69
+
70
+ # Dict-style access (feedparser-compatible)
71
+ print(d["feed"]["title"])
72
+ print(d["entries"][0]["link"])
73
+
74
+ for entry in d.entries:
75
+ print(entry.title)
76
+ print(entry.published_parsed) # time.struct_time
77
+ ```
78
+
79
+ > **Note:** Date fields like `published_parsed` return `time.struct_time` for feedparser compatibility.
80
+
81
+ ### Fetching from URL
82
+
83
+ ```python
84
+ import feedparser_rs
85
+
86
+ # Option 1: Auto-detection (recommended)
87
+ d = feedparser_rs.parse("https://example.com/feed.xml")
88
+
89
+ # Option 2: Explicit URL function
90
+ d = feedparser_rs.parse_url("https://example.com/feed.xml")
91
+
92
+ # With conditional GET for efficient polling
93
+ d = feedparser_rs.parse("https://example.com/feed.xml", etag=cached_etag, modified=cached_modified)
94
+ if d.status == 304:
95
+ print("Feed not modified")
96
+
97
+ # With custom limits
98
+ limits = feedparser_rs.ParserLimits(max_entries=100)
99
+ d = feedparser_rs.parse_with_limits("https://example.com/feed.xml", limits=limits)
100
+ ```
101
+
102
+ > **Tip:** URL fetching supports automatic compression (gzip, deflate, brotli) and follows redirects.
103
+
104
+ ### HTML Sanitization
105
+
106
+ HTML-bearing fields (titles, summaries, `content:encoded`, etc.) are sanitized by default to
107
+ strip dangerous markup, matching feedparser's sanitizer coverage:
108
+
109
+ ```python
110
+ import feedparser_rs
111
+
112
+ # Default: sanitize_html=True, resolve_relative_uris=True
113
+ d = feedparser_rs.parse(feed_data)
114
+
115
+ # Trust this feed source; skip the sanitizer pass
116
+ d = feedparser_rs.parse(feed_data, sanitize_html=False)
117
+ ```
118
+
119
+ > **Important:** Disabling `sanitize_html` is **not recommended** unless you fully trust the feed
120
+ > source and have other security measures in place.
121
+
122
+ ## Migration from feedparser
123
+
124
+ feedparser-rs is designed as a drop-in replacement for Python feedparser:
125
+
126
+ ```python
127
+ # Drop-in replacement
128
+ import feedparser_rs as feedparser
129
+
130
+ # Same API patterns work
131
+ d = feedparser.parse("https://example.com/feed.xml")
132
+ print(d.feed.title)
133
+ print(d["feed"]["title"]) # Dict-style access works too
134
+ print(d.entries[0].link)
135
+
136
+ # Deprecated field names supported
137
+ print(d.feed.description) # → d.feed.subtitle
138
+ print(d.channel.title) # → d.feed.title
139
+ print(d.items[0].guid) # → d.entries[0].id
140
+ ```
141
+
142
+ ### Supported Field Aliases
143
+
144
+ | Old Name | Maps To |
145
+ |----------|---------|
146
+ | `feed.description` | `feed.subtitle` or `feed.summary` |
147
+ | `feed.tagline` | `feed.subtitle` |
148
+ | `feed.copyright` | `feed.rights` |
149
+ | `feed.modified` | `feed.updated` |
150
+ | `channel` | `feed` |
151
+ | `items` | `entries` |
152
+ | `entry.guid` | `entry.id` |
153
+ | `entry.description` | `entry.summary` |
154
+ | `entry.issued` | `entry.published` |
155
+
156
+ ## Advanced Usage
157
+
158
+ ### Custom Resource Limits
159
+
160
+ ```python
161
+ import feedparser_rs
162
+
163
+ limits = feedparser_rs.ParserLimits(
164
+ max_feed_size_bytes=50_000_000, # 50 MB
165
+ max_entries=5_000,
166
+ max_authors=20,
167
+ max_links_per_entry=50,
168
+ )
169
+
170
+ d = feedparser_rs.parse_with_limits(feed_data, limits=limits)
171
+ ```
172
+
173
+ ### Format Detection
174
+
175
+ ```python
176
+ import feedparser_rs
177
+
178
+ version = feedparser_rs.detect_format(feed_data)
179
+ print(version) # "rss20", "atom10", "json11", etc.
180
+ ```
181
+
182
+ ### Podcast Support
183
+
184
+ ```python
185
+ import feedparser_rs
186
+
187
+ d = feedparser_rs.parse(podcast_feed)
188
+
189
+ # iTunes metadata
190
+ if d.feed.itunes:
191
+ print(d.feed.itunes.author)
192
+ print(d.feed.itunes.categories)
193
+
194
+ # Episode metadata
195
+ for entry in d.entries:
196
+ if entry.itunes:
197
+ print(f"Duration: {entry.itunes.duration}") # e.g. "01:30:00"
198
+
199
+ # Podcast 2.0: episode-level value split, chat rooms, etc.
200
+ if entry.podcast and entry.podcast.value:
201
+ print(f"Time splits: {len(entry.podcast.value.time_splits)}")
202
+ ```
203
+
204
+ ## API Reference
205
+
206
+ ### Functions
207
+
208
+ - `parse(source, etag=None, modified=None, user_agent=None, sanitize_html=True, resolve_relative_uris=True)` — Parse feed from bytes, str, or URL (auto-detected)
209
+ - `parse_url(url, etag=None, modified=None, user_agent=None, sanitize_html=True, resolve_relative_uris=True)` — Fetch and parse feed from URL
210
+ - `parse_with_limits(source, etag=None, modified=None, user_agent=None, limits=None, sanitize_html=True, resolve_relative_uris=True)` — Parse with custom resource limits
211
+ - `parse_url_with_limits(url, etag=None, modified=None, user_agent=None, limits=None, sanitize_html=True, resolve_relative_uris=True)` — Fetch and parse with custom limits
212
+ - `detect_format(source)` — Detect feed format without full parsing
213
+
214
+ ### Classes
215
+
216
+ - `FeedParserDict` — Parsed feed result (supports both attribute and dict-style access)
217
+ - `.feed` / `['feed']` — Feed metadata
218
+ - `.entries` / `['entries']` — List of entries
219
+ - `.bozo` — True if parsing errors occurred
220
+ - `.version` — Feed version string
221
+ - `.encoding` — Character encoding
222
+ - `.status` — HTTP status code (for URL fetches)
223
+ - `.etag` — ETag header (for conditional GET)
224
+ - `.modified` — Last-Modified header (for conditional GET)
225
+
226
+ - `ParserLimits` — Resource limits configuration
227
+
228
+ ## Performance
229
+
230
+ Benchmarks vs Python feedparser on Apple M1 Pro:
231
+
232
+ | Operation | feedparser-rs | Python feedparser | Speedup |
233
+ |-----------|---------------|-------------------|---------|
234
+ | Parse 2 KB RSS | 0.01 ms | 0.9 ms | **90x** |
235
+ | Parse 20 KB RSS | 0.09 ms | 8.5 ms | **94x** |
236
+ | Parse 200 KB RSS | 0.94 ms | 85 ms | **90x** |
237
+
238
+ > **Tip:** For maximum performance, pass `bytes` instead of `str` to avoid UTF-8 re-encoding.
239
+
240
+ ## Platform Support
241
+
242
+ Pre-built wheels available for:
243
+
244
+ | Platform | Architecture |
245
+ |----------|--------------|
246
+ | macOS | Intel (x64), Apple Silicon (arm64) |
247
+ | Linux | x64, arm64 |
248
+ | Windows | x64 |
249
+
250
+ Supported Python versions: 3.10, 3.11, 3.12, 3.13, 3.14
251
+
252
+ ## Development
253
+
254
+ ```bash
255
+ git clone https://github.com/bug-ops/feedparser-rs
256
+ cd feedparser-rs/crates/feedparser-rs-py
257
+ pip install maturin
258
+ maturin develop
259
+ ```
260
+
261
+ ## License
262
+
263
+ Licensed under either of:
264
+
265
+ - [Apache License, Version 2.0](../../LICENSE-APACHE)
266
+ - [MIT License](../../LICENSE-MIT)
267
+
268
+ at your option.
269
+
270
+ ## Links
271
+
272
+ - [GitHub](https://github.com/bug-ops/feedparser-rs)
273
+ - [PyPI](https://pypi.org/project/feedparser-rs/)
274
+ - [Rust API Documentation](https://docs.rs/feedparser-rs)
275
+ - [Changelog](../../CHANGELOG.md)
276
+
@@ -0,0 +1,7 @@
1
+ feedparser_rs/__init__.py,sha256=qDKdYY65hMg4BP8uI7Z3byvMmrKqo5oyGYuarY0ahPA,910
2
+ feedparser_rs/_feedparser_rs.cp315-win_amd64.pyd,sha256=qQrrJ0uKQQLWDHjQfyqEfsh4_q6bO1XV0-VAqS5C5FU,6905856
3
+ feedparser_rs/py.typed,sha256=H2JJLtf0lnw9xdu8JDmV7kAT90Z8HJnavchzQ5jnSek,36
4
+ feedparser_rs-0.7.2.dist-info/METADATA,sha256=sfkXp2u3_EQI8NsKYjDd838MJLluAHBRyHBr4b8yOqU,9074
5
+ feedparser_rs-0.7.2.dist-info/WHEEL,sha256=Q5QdGvjBfn8x6ihg-B4VQuuGKk7DT67L9DVrwEH_qj8,97
6
+ feedparser_rs-0.7.2.dist-info/sboms/feedparser-rs-py.cyclonedx.json,sha256=Fk3sLmyQoqgtP0dhLFiZETgtsMthfDhEmR6tSDPMtJY,215588
7
+ feedparser_rs-0.7.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.16.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp315-cp315-win_amd64