watchdiff-core 0.2.2__tar.gz → 0.2.3__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 (55) hide show
  1. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/PKG-INFO +27 -1
  2. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/README.md +26 -0
  3. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/pyproject.toml +1 -1
  4. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/fetcher/fetcher.py +8 -0
  5. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/models.py +1 -0
  6. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/.github/workflows/ci.yml +0 -0
  7. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/.github/workflows/release-testpypi.yml +0 -0
  8. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/.github/workflows/release.yml +0 -0
  9. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/.gitignore +0 -0
  10. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/.python-version +0 -0
  11. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/LICENSE +0 -0
  12. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/main.py +0 -0
  13. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/tests/__init__.py +0 -0
  14. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/tests/test_db.py +0 -0
  15. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/tests/test_watchdiff.py +0 -0
  16. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/uv.lock +0 -0
  17. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/__init__.py +0 -0
  18. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/ai_summarizer/__init__.py +0 -0
  19. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cert_fetcher/__init__.py +0 -0
  20. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cert_models.py +0 -0
  21. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cert_scheduler/__init__.py +0 -0
  22. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cleaner/__init__.py +0 -0
  23. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cleaner/cleaner.py +0 -0
  24. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cli/__init__.py +0 -0
  25. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cli/main.py +0 -0
  26. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/core.py +0 -0
  27. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/cron_parser/__init__.py +0 -0
  28. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_diff/__init__.py +0 -0
  29. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_fetcher/__init__.py +0 -0
  30. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_fetcher/mysql.py +0 -0
  31. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_fetcher/postgres.py +0 -0
  32. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_fetcher/sqlite.py +0 -0
  33. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_models.py +0 -0
  34. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/db_scheduler/__init__.py +0 -0
  35. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/diff/__init__.py +0 -0
  36. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/diff/engine.py +0 -0
  37. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/exporter/__init__.py +0 -0
  38. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/exporter/exporter.py +0 -0
  39. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/fetcher/__init__.py +0 -0
  40. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/fetcher/browser.py +0 -0
  41. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/file_fetcher/__init__.py +0 -0
  42. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/json_path/__init__.py +0 -0
  43. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/mailer/__init__.py +0 -0
  44. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/notifier/__init__.py +0 -0
  45. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/notifier/notifier.py +0 -0
  46. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/parser/__init__.py +0 -0
  47. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/parser/parser.py +0 -0
  48. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/scheduler/__init__.py +0 -0
  49. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/scheduler/scheduler.py +0 -0
  50. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/sitemap/__init__.py +0 -0
  51. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/status_server/__init__.py +0 -0
  52. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/status_server/server.py +0 -0
  53. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/store/__init__.py +0 -0
  54. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/store/sqlite_store.py +0 -0
  55. {watchdiff_core-0.2.2 → watchdiff_core-0.2.3}/watchdiff/store/store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: watchdiff-core
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Lightweight web change monitoring library - clean diffs, AI summaries, file/API/SSL/DB monitoring, structured alerts.
5
5
  Author: WatchDiff Contributors
6
6
  License: BSD-2-Clause
@@ -91,6 +91,7 @@ WatchDiff watches web pages, files, APIs, databases, and SSL certificates - then
91
91
  | Confirm change before alerting | `confirm_after=30` (flapping detection) |
92
92
  | Monitor a sitemap for URL changes | `.watch_sitemap("https://example.com/sitemap.xml")` |
93
93
  | Watch one JSON field only | `json_path="$.data.price"` |
94
+ | Monitor authenticated pages | `cookies={"session": "abc123", "csrftoken": "xyz"}` |
94
95
  | Send email on change | `alert=AlertConfig(email=EmailConfig(to="...", smtp=SmtpConfig(...)))` |
95
96
  | AI summary of changes | `ai_summary=True, ai_provider=AiProvider(type="gemini", api_key="...")` |
96
97
  | Customize the AI prompt | `ai_prompt="Summarize in French."` or `ai_prompt=lambda r: ...` |
@@ -146,6 +147,7 @@ WatchDiff watches web pages, files, APIs, databases, and SSL certificates - then
146
147
  - [Flapping detection](#flapping-detection)
147
148
  - [Sitemap monitoring](#sitemap-monitoring)
148
149
  - [JSON path targeting](#json-path-targeting)
150
+ - [Cookie-based authentication](#cookie-based-authentication)
149
151
  - [Email alerts](#email-alerts)
150
152
  - [API reference](#api-reference)
151
153
  - [`.watch()`](#watchurl--)
@@ -1395,6 +1397,29 @@ value = extract_json_path('{"data": {"price": 42.5}}', "$.data.price")
1395
1397
  # "42.5"
1396
1398
  ```
1397
1399
 
1400
+ ## Cookie-based authentication
1401
+
1402
+ Pass cookies with every request to monitor pages that require a login session. Cookies are merged into the outgoing `Cookie` header on top of any `headers` you supply.
1403
+
1404
+ ```python
1405
+ wd.watch("https://app.example.com/dashboard",
1406
+ cookies={"session": "your-session-token", "csrftoken": "your-csrf-token"},
1407
+ interval=300,
1408
+ on_change=lambda r: print(r.changes))
1409
+ ```
1410
+
1411
+ Combine `cookies` with `headers` — the cookie string is appended to any existing `Cookie` header:
1412
+
1413
+ ```python
1414
+ wd.watch_api("https://api.example.com/account",
1415
+ headers={"Authorization": "Bearer token123"},
1416
+ cookies={"_ga": "GA1.1.0000000000.0000000000"},
1417
+ json_path="$.balance",
1418
+ interval=60)
1419
+ ```
1420
+
1421
+ > Tip: copy cookie values from your browser's DevTools → Network tab → Request Headers.
1422
+
1398
1423
  ## Email alerts
1399
1424
 
1400
1425
  Send email notifications via SMTP when a change is detected. Uses Python stdlib `smtplib` — no extra dependency required.
@@ -1480,6 +1505,7 @@ Register a URL to monitor. All keyword arguments are optional. Returns `self` (c
1480
1505
  | `on_spike` | `Callable \| None` | `None` | Called with `SpikeInfo` when spike is detected |
1481
1506
  | `alert_on_status_change` | `bool` | `False` | Alert when HTTP status code changes (200→503, etc.) |
1482
1507
  | `on_status_change` | `Callable \| None` | `None` | Called with `StatusChangeInfo` on status code change |
1508
+ | `cookies` | `dict[str, str]` | `{}` | Cookies sent with every request — merged into the `Cookie` header (e.g. `{"session": "abc"}`) |
1483
1509
  | `alert` | `AlertConfig \| None` | `None` | Full alert config — use instead of `on_change`/`webhooks` to include email or fine-tune retries |
1484
1510
  | `alert_if` | `Callable[[DiffReport], bool] \| None` | `None` | Custom gate - only alert when this function returns `True` |
1485
1511
  | `expected_status` | `int \| None` | `None` | Fire `on_error` when actual HTTP status differs from this value |
@@ -43,6 +43,7 @@ WatchDiff watches web pages, files, APIs, databases, and SSL certificates - then
43
43
  | Confirm change before alerting | `confirm_after=30` (flapping detection) |
44
44
  | Monitor a sitemap for URL changes | `.watch_sitemap("https://example.com/sitemap.xml")` |
45
45
  | Watch one JSON field only | `json_path="$.data.price"` |
46
+ | Monitor authenticated pages | `cookies={"session": "abc123", "csrftoken": "xyz"}` |
46
47
  | Send email on change | `alert=AlertConfig(email=EmailConfig(to="...", smtp=SmtpConfig(...)))` |
47
48
  | AI summary of changes | `ai_summary=True, ai_provider=AiProvider(type="gemini", api_key="...")` |
48
49
  | Customize the AI prompt | `ai_prompt="Summarize in French."` or `ai_prompt=lambda r: ...` |
@@ -98,6 +99,7 @@ WatchDiff watches web pages, files, APIs, databases, and SSL certificates - then
98
99
  - [Flapping detection](#flapping-detection)
99
100
  - [Sitemap monitoring](#sitemap-monitoring)
100
101
  - [JSON path targeting](#json-path-targeting)
102
+ - [Cookie-based authentication](#cookie-based-authentication)
101
103
  - [Email alerts](#email-alerts)
102
104
  - [API reference](#api-reference)
103
105
  - [`.watch()`](#watchurl--)
@@ -1347,6 +1349,29 @@ value = extract_json_path('{"data": {"price": 42.5}}', "$.data.price")
1347
1349
  # "42.5"
1348
1350
  ```
1349
1351
 
1352
+ ## Cookie-based authentication
1353
+
1354
+ Pass cookies with every request to monitor pages that require a login session. Cookies are merged into the outgoing `Cookie` header on top of any `headers` you supply.
1355
+
1356
+ ```python
1357
+ wd.watch("https://app.example.com/dashboard",
1358
+ cookies={"session": "your-session-token", "csrftoken": "your-csrf-token"},
1359
+ interval=300,
1360
+ on_change=lambda r: print(r.changes))
1361
+ ```
1362
+
1363
+ Combine `cookies` with `headers` — the cookie string is appended to any existing `Cookie` header:
1364
+
1365
+ ```python
1366
+ wd.watch_api("https://api.example.com/account",
1367
+ headers={"Authorization": "Bearer token123"},
1368
+ cookies={"_ga": "GA1.1.0000000000.0000000000"},
1369
+ json_path="$.balance",
1370
+ interval=60)
1371
+ ```
1372
+
1373
+ > Tip: copy cookie values from your browser's DevTools → Network tab → Request Headers.
1374
+
1350
1375
  ## Email alerts
1351
1376
 
1352
1377
  Send email notifications via SMTP when a change is detected. Uses Python stdlib `smtplib` — no extra dependency required.
@@ -1432,6 +1457,7 @@ Register a URL to monitor. All keyword arguments are optional. Returns `self` (c
1432
1457
  | `on_spike` | `Callable \| None` | `None` | Called with `SpikeInfo` when spike is detected |
1433
1458
  | `alert_on_status_change` | `bool` | `False` | Alert when HTTP status code changes (200→503, etc.) |
1434
1459
  | `on_status_change` | `Callable \| None` | `None` | Called with `StatusChangeInfo` on status code change |
1460
+ | `cookies` | `dict[str, str]` | `{}` | Cookies sent with every request — merged into the `Cookie` header (e.g. `{"session": "abc"}`) |
1435
1461
  | `alert` | `AlertConfig \| None` | `None` | Full alert config — use instead of `on_change`/`webhooks` to include email or fine-tune retries |
1436
1462
  | `alert_if` | `Callable[[DiffReport], bool] \| None` | `None` | Custom gate - only alert when this function returns `True` |
1437
1463
  | `expected_status` | `int \| None` | `None` | Fire `on_error` when actual HTTP status differs from this value |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "watchdiff-core"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Lightweight web change monitoring library - clean diffs, AI summaries, file/API/SSL/DB monitoring, structured alerts."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -85,6 +85,10 @@ class Fetcher:
85
85
  FetchError: after all retries are exhausted.
86
86
  """
87
87
  headers = {**_DEFAULT_ACCEPT_HEADERS, "User-Agent": _pick_ua(config), **config.headers}
88
+ if config.cookies:
89
+ existing = headers.get("Cookie", "")
90
+ cookie_str = "; ".join(f"{k}={v}" for k, v in config.cookies.items())
91
+ headers["Cookie"] = f"{existing}; {cookie_str}" if existing else cookie_str
88
92
  proxy = _pick_proxy(config)
89
93
 
90
94
  client_kwargs: dict = {"timeout": config.timeout, "follow_redirects": True}
@@ -133,6 +137,10 @@ class AsyncFetcher:
133
137
  FetchError: after all retries are exhausted.
134
138
  """
135
139
  headers = {**_DEFAULT_ACCEPT_HEADERS, "User-Agent": _pick_ua(config), **config.headers}
140
+ if config.cookies:
141
+ existing = headers.get("Cookie", "")
142
+ cookie_str = "; ".join(f"{k}={v}" for k, v in config.cookies.items())
143
+ headers["Cookie"] = f"{existing}; {cookie_str}" if existing else cookie_str
136
144
  proxy = _pick_proxy(config)
137
145
 
138
146
  client_kwargs: dict = {"timeout": config.timeout, "follow_redirects": True}
@@ -53,6 +53,7 @@ class WatchConfig:
53
53
  interval: int = 300 # seconds between checks
54
54
  label: str | None = None # human-readable name for this watch
55
55
  headers: dict[str, str] = field(default_factory=dict)
56
+ cookies: dict[str, str] = field(default_factory=dict)
56
57
  timeout: int = 15 # HTTP timeout in seconds
57
58
  ignore_selectors: list[str] = field(default_factory=list)
58
59
  ignore_patterns: list[str] = field(default_factory=list)
File without changes
File without changes
File without changes