webchanges 3.36.0__tar.gz → 3.37.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.
- {webchanges-3.36.0/webchanges.egg-info → webchanges-3.37.0}/PKG-INFO +33 -30
- {webchanges-3.36.0 → webchanges-3.37.0}/README.rst +30 -27
- {webchanges-3.36.0 → webchanges-3.37.0}/pyproject.toml +13 -4
- {webchanges-3.36.0 → webchanges-3.37.0}/tools/get_manpages_parser.py +6 -2
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/__init__.py +1 -1
- webchanges-3.37.0/webchanges/__main__.py +11 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_resources/config.schema.json +22 -5
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_resources/jobs.schema.json +66 -19
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_vendored/headers.py +1 -1
- webchanges-3.37.0/webchanges/_vendored/packaging_version.py +1469 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_vendored/typeguard.py +70 -54
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/cli.py +461 -29
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/command.py +89 -305
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/differs.py +308 -85
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/__init__.py +2 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_base.py +4 -4
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_document.py +1 -1
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_text.py +46 -1
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/handler.py +14 -8
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/jobs/_base.py +22 -14
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/jobs/_browser.py +229 -99
- webchanges-3.37.0/webchanges/jobs/_shell.py +258 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/jobs/_url.py +9 -8
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/main.py +8 -2
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/__init__.py +0 -3
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_base.py +27 -16
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_config.py +34 -1
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_yaml.py +37 -22
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/util.py +114 -34
- webchanges-3.37.0/webchanges/worker.py +313 -0
- {webchanges-3.36.0 → webchanges-3.37.0/webchanges.egg-info}/PKG-INFO +33 -30
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges.egg-info/SOURCES.txt +0 -1
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges.egg-info/requires.txt +2 -2
- webchanges-3.36.0/webchanges/__main__.py +0 -10
- webchanges-3.36.0/webchanges/_vendored/packaging_version.py +0 -807
- webchanges-3.36.0/webchanges/jobs/_shell.py +0 -91
- webchanges-3.36.0/webchanges/reporters/_filter.py +0 -59
- webchanges-3.36.0/webchanges/worker.py +0 -245
- {webchanges-3.36.0 → webchanges-3.37.0}/LICENSE.md +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/MANIFEST.in +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/requirements.txt +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/setup.cfg +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/setup.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_resources/__init__.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/_vendored/__init__.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/config.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_encoding.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_html.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/filters/_shell.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/jobs/__init__.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/jobs/_exceptions.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/mailer.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/py.typed +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_browser.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_chat.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_email.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_stdout.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_system.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/reporters/_web.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/__init__.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_base.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_minidb.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_redis.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_sqlite3.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage/_ssdb.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges/storage_minidb.py +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges.egg-info/dependency_links.txt +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges.egg-info/entry_points.txt +0 -0
- {webchanges-3.36.0 → webchanges-3.37.0}/webchanges.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webchanges
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.37.0
|
|
4
4
|
Summary: Web Changes Delivered. AI-Summarized. Totally Anonymous.
|
|
5
5
|
Author-email: Mike Borsetti <mike+webchanges@borsetti.com>
|
|
6
6
|
Maintainer-email: Mike Borsetti <mike+webchanges@borsetti.com>
|
|
@@ -76,9 +76,9 @@ Provides-Extra: pypdf-crypto
|
|
|
76
76
|
Requires-Dist: pypdf; extra == "pypdf-crypto"
|
|
77
77
|
Requires-Dist: cryptography; extra == "pypdf-crypto"
|
|
78
78
|
Provides-Extra: deepdiff
|
|
79
|
-
Requires-Dist: deepdiff; extra == "deepdiff"
|
|
79
|
+
Requires-Dist: deepdiff>=8.0; extra == "deepdiff"
|
|
80
80
|
Provides-Extra: deepdiff-xml
|
|
81
|
-
Requires-Dist: deepdiff; extra == "deepdiff-xml"
|
|
81
|
+
Requires-Dist: deepdiff>=8.0; extra == "deepdiff-xml"
|
|
82
82
|
Requires-Dist: xmltodict; extra == "deepdiff-xml"
|
|
83
83
|
Provides-Extra: imagediff
|
|
84
84
|
Requires-Dist: Pillow; extra == "imagediff"
|
|
@@ -118,26 +118,35 @@ notifications and AI-powered summaries to your favorite `platform
|
|
|
118
118
|
<https://webchanges.readthedocs.io/en/stable/introduction.html#reporters>`__.
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
**
|
|
121
|
+
Highlights
|
|
122
|
+
==========
|
|
123
|
+
- **AI-powered change summaries** via Gemini (`ai_google differ
|
|
124
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__, BETA).
|
|
125
|
+
- **Structural diffs for JSON and XML** via the `deepdiff differ
|
|
126
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#deepdiff-diff>`__.
|
|
127
|
+
- **Visual diffs for images** via the `image differ
|
|
128
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#image-diff>`__ (BETA).
|
|
129
|
+
- **Bypass TLS/JA3 fingerprinting** with the optional `curl_cffi
|
|
130
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#http-client>`__ HTTP client.
|
|
131
|
+
- **JSON-Schema-validated** ``jobs.yaml`` and ``config.yaml`` for editor autocompletion and inline validation.
|
|
124
132
|
|
|
125
|
-
For the best experience, use the current version of `Python <https://www.python.org/downloads/>`__. We also support
|
|
126
|
-
older Python versions for 3 years after they're replaced by a newer one; we just ask that you use the most up-to-date
|
|
127
|
-
bug and security fix release from that older version.
|
|
128
133
|
|
|
129
|
-
|
|
134
|
+
Requirements
|
|
135
|
+
============
|
|
136
|
+
**webchanges** requires |support|. For the best experience, use the current version of `Python
|
|
137
|
+
<https://www.python.org/downloads/>`__; older Python versions are supported for 3 years after they're replaced. Free-threaded Python is supported, though some
|
|
138
|
+
optional dependencies may not be.
|
|
130
139
|
|
|
131
140
|
For Generative AI summaries (BETA), you need a free `API Key from Google Cloud AI Studio
|
|
132
141
|
<https://aistudio.google.com/app/apikey>`__ (see `here
|
|
133
|
-
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google>`__).
|
|
142
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__).
|
|
134
143
|
|
|
135
144
|
|
|
136
145
|
Installation
|
|
137
146
|
============
|
|
138
147
|
|pypi_version| |format| |status|
|
|
139
148
|
|
|
140
|
-
Install **webchanges** with
|
|
149
|
+
Install **webchanges** with `uv <https://docs.astral.sh/uv/>`__ (recommended):
|
|
141
150
|
|
|
142
151
|
.. code-block:: bash
|
|
143
152
|
|
|
@@ -149,22 +158,18 @@ or with ``pip``:
|
|
|
149
158
|
|
|
150
159
|
pip install webchanges
|
|
151
160
|
|
|
152
|
-
|
|
161
|
+
Other ways to run
|
|
153
162
|
-----------------
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
------------------
|
|
160
|
-
**webchanges** can easily run as a `GitHub Action <https://www.docker.com/>`__! You will find an implementation
|
|
161
|
-
`here <https://github.com/swimmwatch/webchanges-action>`__.
|
|
163
|
+
- In a `Docker <https://www.docker.com/>`__ container: a minimal implementation (no browser) is `here
|
|
164
|
+
<https://github.com/yubiuser/webchanges-docker>`__, and one with a browser is `here
|
|
165
|
+
<https://github.com/jhedlund/webchanges-docker>`__.
|
|
166
|
+
- As a `GitHub Action <https://docs.github.com/en/actions>`__: an implementation is `here
|
|
167
|
+
<https://github.com/swimmwatch/webchanges-action>`__.
|
|
162
168
|
|
|
163
169
|
|
|
164
170
|
Documentation |readthedocs|
|
|
165
171
|
===========================
|
|
166
|
-
The documentation is hosted on `Read the Docs <https://webchanges.readthedocs.io/>`__.
|
|
167
|
-
high-level architectural overview is available on `DeepWiki <https://deepwiki.com/mborsetti/webchanges>`__.
|
|
172
|
+
The documentation is hosted on `Read the Docs <https://webchanges.readthedocs.io/>`__.
|
|
168
173
|
|
|
169
174
|
|
|
170
175
|
Quick Start
|
|
@@ -238,13 +243,11 @@ licensed under a `BSD 3-Clause License
|
|
|
238
243
|
<https://raw.githubusercontent.com/thp/urlwatch/346b25914b0418342ffe2fb0529bed702fddc01f/COPYING>`__).
|
|
239
244
|
|
|
240
245
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
<https://
|
|
246
|
-
For upgrading from **urlwatch** to **webchanges** (using the same job and
|
|
247
|
-
configuration files), see `here <https://webchanges.readthedocs.io/en/stable/upgrading.html>`__.
|
|
246
|
+
Relationship with **urlwatch**
|
|
247
|
+
==============================
|
|
248
|
+
This project is a fork of `urlwatch 2.21
|
|
249
|
+
<https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ and has since added many features;
|
|
250
|
+
see the `comparison <https://webchanges.readthedocs.io/en/stable/_static/webchanges-vs-urlwatch.html>`__.
|
|
248
251
|
|
|
249
252
|
|
|
250
253
|
.. |support| image:: https://img.shields.io/pypi/pyversions/webchanges.svg
|
|
@@ -14,26 +14,35 @@ notifications and AI-powered summaries to your favorite `platform
|
|
|
14
14
|
<https://webchanges.readthedocs.io/en/stable/introduction.html#reporters>`__.
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
**
|
|
17
|
+
Highlights
|
|
18
|
+
==========
|
|
19
|
+
- **AI-powered change summaries** via Gemini (`ai_google differ
|
|
20
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__, BETA).
|
|
21
|
+
- **Structural diffs for JSON and XML** via the `deepdiff differ
|
|
22
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#deepdiff-diff>`__.
|
|
23
|
+
- **Visual diffs for images** via the `image differ
|
|
24
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#image-diff>`__ (BETA).
|
|
25
|
+
- **Bypass TLS/JA3 fingerprinting** with the optional `curl_cffi
|
|
26
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#http-client>`__ HTTP client.
|
|
27
|
+
- **JSON-Schema-validated** ``jobs.yaml`` and ``config.yaml`` for editor autocompletion and inline validation.
|
|
20
28
|
|
|
21
|
-
For the best experience, use the current version of `Python <https://www.python.org/downloads/>`__. We also support
|
|
22
|
-
older Python versions for 3 years after they're replaced by a newer one; we just ask that you use the most up-to-date
|
|
23
|
-
bug and security fix release from that older version.
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
Requirements
|
|
31
|
+
============
|
|
32
|
+
**webchanges** requires |support|. For the best experience, use the current version of `Python
|
|
33
|
+
<https://www.python.org/downloads/>`__; older Python versions are supported for 3 years after they're replaced. Free-threaded Python is supported, though some
|
|
34
|
+
optional dependencies may not be.
|
|
26
35
|
|
|
27
36
|
For Generative AI summaries (BETA), you need a free `API Key from Google Cloud AI Studio
|
|
28
37
|
<https://aistudio.google.com/app/apikey>`__ (see `here
|
|
29
|
-
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google>`__).
|
|
38
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__).
|
|
30
39
|
|
|
31
40
|
|
|
32
41
|
Installation
|
|
33
42
|
============
|
|
34
43
|
|pypi_version| |format| |status|
|
|
35
44
|
|
|
36
|
-
Install **webchanges** with
|
|
45
|
+
Install **webchanges** with `uv <https://docs.astral.sh/uv/>`__ (recommended):
|
|
37
46
|
|
|
38
47
|
.. code-block:: bash
|
|
39
48
|
|
|
@@ -45,22 +54,18 @@ or with ``pip``:
|
|
|
45
54
|
|
|
46
55
|
pip install webchanges
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
Other ways to run
|
|
49
58
|
-----------------
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
------------------
|
|
56
|
-
**webchanges** can easily run as a `GitHub Action <https://www.docker.com/>`__! You will find an implementation
|
|
57
|
-
`here <https://github.com/swimmwatch/webchanges-action>`__.
|
|
59
|
+
- In a `Docker <https://www.docker.com/>`__ container: a minimal implementation (no browser) is `here
|
|
60
|
+
<https://github.com/yubiuser/webchanges-docker>`__, and one with a browser is `here
|
|
61
|
+
<https://github.com/jhedlund/webchanges-docker>`__.
|
|
62
|
+
- As a `GitHub Action <https://docs.github.com/en/actions>`__: an implementation is `here
|
|
63
|
+
<https://github.com/swimmwatch/webchanges-action>`__.
|
|
58
64
|
|
|
59
65
|
|
|
60
66
|
Documentation |readthedocs|
|
|
61
67
|
===========================
|
|
62
|
-
The documentation is hosted on `Read the Docs <https://webchanges.readthedocs.io/>`__.
|
|
63
|
-
high-level architectural overview is available on `DeepWiki <https://deepwiki.com/mborsetti/webchanges>`__.
|
|
68
|
+
The documentation is hosted on `Read the Docs <https://webchanges.readthedocs.io/>`__.
|
|
64
69
|
|
|
65
70
|
|
|
66
71
|
Quick Start
|
|
@@ -134,13 +139,11 @@ licensed under a `BSD 3-Clause License
|
|
|
134
139
|
<https://raw.githubusercontent.com/thp/urlwatch/346b25914b0418342ffe2fb0529bed702fddc01f/COPYING>`__).
|
|
135
140
|
|
|
136
141
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
<https://
|
|
142
|
-
For upgrading from **urlwatch** to **webchanges** (using the same job and
|
|
143
|
-
configuration files), see `here <https://webchanges.readthedocs.io/en/stable/upgrading.html>`__.
|
|
142
|
+
Relationship with **urlwatch**
|
|
143
|
+
==============================
|
|
144
|
+
This project is a fork of `urlwatch 2.21
|
|
145
|
+
<https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ and has since added many features;
|
|
146
|
+
see the `comparison <https://webchanges.readthedocs.io/en/stable/_static/webchanges-vs-urlwatch.html>`__.
|
|
144
147
|
|
|
145
148
|
|
|
146
149
|
.. |support| image:: https://img.shields.io/pypi/pyversions/webchanges.svg
|
|
@@ -65,7 +65,7 @@ webchanges = 'webchanges.cli:main'
|
|
|
65
65
|
use_browser = ['playwright', 'psutil']
|
|
66
66
|
# filters
|
|
67
67
|
# lxml is now optional with beautifulsoup4
|
|
68
|
-
# note: also update the list of all possible dependencies in show_detailed_versions() in
|
|
68
|
+
# note: also update the list of all possible dependencies in show_detailed_versions() in cli.py!
|
|
69
69
|
beautify = ['beautifulsoup4', 'jsbeautifier', 'cssbeautifier']
|
|
70
70
|
bs4 = ['beautifulsoup4']
|
|
71
71
|
html5lib = ['html5lib']
|
|
@@ -76,8 +76,9 @@ pdf2text = ['pdftotext']
|
|
|
76
76
|
pypdf = ['pypdf']
|
|
77
77
|
pypdf_crypto = ['pypdf', 'cryptography']
|
|
78
78
|
# differs
|
|
79
|
-
deepdiff
|
|
80
|
-
|
|
79
|
+
# deepdiff >= 8.0 is required for threshold_to_diff_deeper
|
|
80
|
+
deepdiff = ['deepdiff >= 8.0']
|
|
81
|
+
deepdiff_xml = ['deepdiff >= 8.0', 'xmltodict']
|
|
81
82
|
imagediff = ['Pillow']
|
|
82
83
|
# reporters
|
|
83
84
|
matrix = ['matrix_client']
|
|
@@ -210,6 +211,14 @@ report_level = 'WARNING'
|
|
|
210
211
|
# log_cli = true
|
|
211
212
|
minversion = '9.0.2'
|
|
212
213
|
testpaths = ['tests']
|
|
214
|
+
filterwarnings = [
|
|
215
|
+
# Fail tests that leak sqlite3 connections. Scoped by message so third-party ResourceWarnings (e.g.
|
|
216
|
+
# asyncio/playwright transports) don't destabilize the suite. The second entry is required because the warning
|
|
217
|
+
# is emitted during garbage collection: the error raised there is unraisable, and only surfaces as a test
|
|
218
|
+
# failure through pytest's unraisable-exception plugin (as a PytestUnraisableExceptionWarning).
|
|
219
|
+
'error:unclosed database:ResourceWarning',
|
|
220
|
+
'error:(?s).*unclosed database:pytest.PytestUnraisableExceptionWarning',
|
|
221
|
+
]
|
|
213
222
|
|
|
214
223
|
# pytest-playwright
|
|
215
224
|
# addopts = ['--browser', 'chromium', '--browser-channel', 'chrome']
|
|
@@ -293,7 +302,7 @@ ignore = [
|
|
|
293
302
|
'RUF012', # Mutable class attributes should be annotated with `typing.ClassVar`
|
|
294
303
|
'SIM105', # Use contextlib.suppress({exception}) instead of try-except-pass
|
|
295
304
|
'SIM115', # Use a context manager for opening files
|
|
296
|
-
'TD002', #
|
|
305
|
+
'TD002', # Missing author in TODO
|
|
297
306
|
'TD003', # Missing issue link for this TODO
|
|
298
307
|
]
|
|
299
308
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
|
-
from argparse import ArgumentParser
|
|
5
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from argparse import ArgumentParser
|
|
9
|
+
|
|
6
10
|
|
|
7
11
|
sys.path.insert(0, str(Path.cwd()))
|
|
8
12
|
|
|
@@ -22,7 +22,7 @@ __project_name__ = str(__package__)
|
|
|
22
22
|
# * MINOR version when you add functionality in a backwards compatible manner, and
|
|
23
23
|
# * MICRO or PATCH version when you make backwards compatible bug fixes. We no longer use '0'
|
|
24
24
|
# If unsure on increments, use pkg_resources.parse_version to parse
|
|
25
|
-
__version__ = '3.
|
|
25
|
+
__version__ = '3.37.0'
|
|
26
26
|
__description__ = (
|
|
27
27
|
'Check web (or command output) for changes since last run and notify.\n\nAnonymously alerts you of web changes.'
|
|
28
28
|
)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/mborsetti/webchanges/refs/heads/main/webchanges/_resources/config.schema.json",
|
|
3
4
|
"title": "Webchanges Configuration File",
|
|
4
5
|
"description": "JSON Schema for the webchanges config.yaml configuration file.",
|
|
5
6
|
"type": "object",
|
|
6
|
-
"required": ["display", "report", "job_defaults", "differ_defaults", "database", "footnote"],
|
|
7
|
+
"required": ["display", "report", "job_defaults", "differ_defaults", "database", "footnote", "version_check"],
|
|
7
8
|
"properties": {
|
|
8
9
|
"display": {
|
|
9
10
|
"$ref": "#/$defs/_ConfigDisplay",
|
|
@@ -29,6 +30,10 @@
|
|
|
29
30
|
"type": ["string", "null"],
|
|
30
31
|
"description": "Optional text appended to the footer of every report (text, html and markdown). Set to null to disable.",
|
|
31
32
|
"default": null
|
|
33
|
+
},
|
|
34
|
+
"version_check": {
|
|
35
|
+
"$ref": "#/$defs/_ConfigVersionCheck",
|
|
36
|
+
"description": "Settings for the once-a-day check against PyPi for a newer release of webchanges."
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
39
|
"additionalProperties": false,
|
|
@@ -37,7 +42,7 @@
|
|
|
37
42
|
"title": "Display",
|
|
38
43
|
"description": "Which job outcomes appear in reports. Changes are always reported.",
|
|
39
44
|
"type": "object",
|
|
40
|
-
"required": ["new", "error", "unchanged"
|
|
45
|
+
"required": ["new", "error", "unchanged"],
|
|
41
46
|
"properties": {
|
|
42
47
|
"new": {
|
|
43
48
|
"type": "boolean",
|
|
@@ -55,9 +60,8 @@
|
|
|
55
60
|
"default": false
|
|
56
61
|
},
|
|
57
62
|
"empty-diff": {
|
|
58
|
-
"
|
|
59
|
-
"description": "Deprecated
|
|
60
|
-
"default": false,
|
|
63
|
+
"enum": [false],
|
|
64
|
+
"description": "Deprecated; use additions_only in the job instead.",
|
|
61
65
|
"deprecated": true
|
|
62
66
|
}
|
|
63
67
|
}
|
|
@@ -928,6 +932,19 @@
|
|
|
928
932
|
"default": 4
|
|
929
933
|
}
|
|
930
934
|
}
|
|
935
|
+
},
|
|
936
|
+
"_ConfigVersionCheck": {
|
|
937
|
+
"title": "Version Check",
|
|
938
|
+
"description": "Settings for the once-a-day check against PyPi for a newer release of webchanges.",
|
|
939
|
+
"type": "object",
|
|
940
|
+
"required": ["enabled"],
|
|
941
|
+
"properties": {
|
|
942
|
+
"enabled": {
|
|
943
|
+
"type": "boolean",
|
|
944
|
+
"description": "Whether to query PyPi for a newer release. The result is cached on disk for 24 hours, so this hits the network at most once per day. Set to false to disable the check entirely (no network call, no upgrade nudge in reports).",
|
|
945
|
+
"default": true
|
|
946
|
+
}
|
|
947
|
+
}
|
|
931
948
|
}
|
|
932
949
|
}
|
|
933
950
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/mborsetti/webchanges/refs/heads/main/webchanges/_resources/jobs.schema.json",
|
|
3
4
|
"title": "Webchanges Jobs Configuration",
|
|
4
|
-
"description": "JSON Schema for each job in
|
|
5
|
+
"description": "JSON Schema for each job in webchanges' jobs.yaml configuration file",
|
|
5
6
|
"type": "object",
|
|
6
7
|
"oneOf": [{ "required": ["url"] }, { "required": ["command"] }],
|
|
7
8
|
"properties": {
|
|
@@ -58,10 +59,23 @@
|
|
|
58
59
|
"type": ["integer", "number"],
|
|
59
60
|
"description": "Request timeout in seconds."
|
|
60
61
|
},
|
|
62
|
+
"same_site_delay": {
|
|
63
|
+
"type": ["integer", "number"],
|
|
64
|
+
"description": "Number of seconds to wait before retrieving the URL when an earlier job in the list already targets the same site (network location). The first (or only) job for a given site is never delayed. Use it to stagger jobs that would otherwise hit the same site at the same instant and get rate-limited or blocked."
|
|
65
|
+
},
|
|
66
|
+
"delay": {
|
|
67
|
+
"type": ["integer", "number"],
|
|
68
|
+
"description": "Number of seconds to wait before retrieving the URL (e.g. to stagger jobs that hit the same site, or to space out requests to a slow or rate-limited server)."
|
|
69
|
+
},
|
|
61
70
|
"ignore_connection_errors": {
|
|
62
71
|
"type": "boolean",
|
|
63
72
|
"description": "If true, connection errors are ignored (no report sent)."
|
|
64
73
|
},
|
|
74
|
+
"empty_as_transient": {
|
|
75
|
+
"type": "boolean",
|
|
76
|
+
"description": "If true, an empty response is treated as a transient HTTP error (synthetic status code 999) instead of valid content, preserving the last non-empty snapshot. Combine with max_tries or 'ignore_http_error_codes: 999' to control error reporting. Not for jobs with use_browser.",
|
|
77
|
+
"default": false
|
|
78
|
+
},
|
|
65
79
|
"no_redirects": {
|
|
66
80
|
"type": "boolean",
|
|
67
81
|
"description": "If true, do not follow HTTP redirects."
|
|
@@ -170,6 +184,11 @@
|
|
|
170
184
|
},
|
|
171
185
|
"description": "Resource types to block from loading (browser jobs)."
|
|
172
186
|
},
|
|
187
|
+
"connect_over_cdp": {
|
|
188
|
+
"oneOf": [{ "type": "boolean" }, { "type": "string", "format": "uri" }],
|
|
189
|
+
"description": "Attach Playwright to an already-running Chromium browser via the Chrome DevTools Protocol (browser jobs). 'true' uses the default endpoint ws://127.0.0.1:58489/devtools/browser; a string is used as the CDP WebSocket URL.",
|
|
190
|
+
"default": false
|
|
191
|
+
},
|
|
173
192
|
"evaluate": {
|
|
174
193
|
"type": "string",
|
|
175
194
|
"description": "JavaScript code to execute in the page context (browser jobs)."
|
|
@@ -180,7 +199,7 @@
|
|
|
180
199
|
},
|
|
181
200
|
"ignore_default_args": {
|
|
182
201
|
"oneOf": [{ "type": "boolean" }, { "type": "array", "items": { "type": "string" } }],
|
|
183
|
-
"description": "Override
|
|
202
|
+
"description": "Override browser default arguments (browser jobs).",
|
|
184
203
|
"default": false
|
|
185
204
|
},
|
|
186
205
|
"ignore_https_errors": {
|
|
@@ -204,14 +223,18 @@
|
|
|
204
223
|
"type": "string",
|
|
205
224
|
"description": "Referer header value (browser jobs)."
|
|
206
225
|
},
|
|
226
|
+
"stealth": {
|
|
227
|
+
"type": "boolean",
|
|
228
|
+
"description": "Use stealth mode (browser jobs)."
|
|
229
|
+
},
|
|
207
230
|
"switches": {
|
|
208
231
|
"type": "array",
|
|
209
232
|
"items": { "type": "string" },
|
|
210
|
-
"description": "Additional
|
|
233
|
+
"description": "Additional browser command-line switches (browser jobs)."
|
|
211
234
|
},
|
|
212
235
|
"user_data_dir": {
|
|
213
236
|
"type": "string",
|
|
214
|
-
"description": "Path to a
|
|
237
|
+
"description": "Path to a browser user data directory (for persistence/auth with use_browser)."
|
|
215
238
|
},
|
|
216
239
|
"wait_for_function": {
|
|
217
240
|
"oneOf": [
|
|
@@ -444,6 +467,27 @@
|
|
|
444
467
|
"type": "boolean",
|
|
445
468
|
"description": "Use compact output format.",
|
|
446
469
|
"default": false
|
|
470
|
+
},
|
|
471
|
+
"cutoff_distance_for_pairs": {
|
|
472
|
+
"type": "number",
|
|
473
|
+
"minimum": 0,
|
|
474
|
+
"maximum": 1,
|
|
475
|
+
"description": "With ignore_order, two changed items are paired and compared in depth only if their deep distance is below this value; otherwise they are reported as one item removed plus one added (deepdiff library's own default is 0.3).",
|
|
476
|
+
"default": 1.0
|
|
477
|
+
},
|
|
478
|
+
"cutoff_intersection_for_pairs": {
|
|
479
|
+
"type": "number",
|
|
480
|
+
"minimum": 0,
|
|
481
|
+
"maximum": 1,
|
|
482
|
+
"description": "With ignore_order, pairing of changed items is attempted only if the intersection distance of the two iterables is below this value; otherwise each changed item is reported in its entirety (deepdiff library's own default is 0.7).",
|
|
483
|
+
"default": 1.0
|
|
484
|
+
},
|
|
485
|
+
"threshold_to_diff_deeper": {
|
|
486
|
+
"type": "number",
|
|
487
|
+
"minimum": 0,
|
|
488
|
+
"maximum": 1,
|
|
489
|
+
"description": "The fraction of keys two dictionaries must share for them to be compared key by key instead of being reported as one whole new value (deepdiff library's own default is 0.33).",
|
|
490
|
+
"default": 0
|
|
447
491
|
}
|
|
448
492
|
},
|
|
449
493
|
"required": ["name"],
|
|
@@ -644,21 +688,9 @@
|
|
|
644
688
|
},
|
|
645
689
|
"definitions": {
|
|
646
690
|
"filterList": {
|
|
647
|
-
"
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
"description": "A single filter name (e.g. 'html2text', 'sha1sum')."
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
"type": "array",
|
|
654
|
-
"items": { "$ref": "#/definitions/filterItem" },
|
|
655
|
-
"description": "List of filters to apply in order."
|
|
656
|
-
},
|
|
657
|
-
{
|
|
658
|
-
"$ref": "#/definitions/filterItemObject",
|
|
659
|
-
"description": "A single filter as an object."
|
|
660
|
-
}
|
|
661
|
-
]
|
|
691
|
+
"type": "array",
|
|
692
|
+
"items": { "$ref": "#/definitions/filterItem" },
|
|
693
|
+
"description": "List of filters to apply in order."
|
|
662
694
|
},
|
|
663
695
|
"filterItem": {
|
|
664
696
|
"oneOf": [
|
|
@@ -735,6 +767,21 @@
|
|
|
735
767
|
],
|
|
736
768
|
"description": "Beautifies HTML using BeautifulSoup."
|
|
737
769
|
},
|
|
770
|
+
"between": {
|
|
771
|
+
"type": "object",
|
|
772
|
+
"properties": {
|
|
773
|
+
"start": {
|
|
774
|
+
"type": "string",
|
|
775
|
+
"description": "Regular expression matching the line that opens the block (this line is not kept)."
|
|
776
|
+
},
|
|
777
|
+
"end": {
|
|
778
|
+
"type": "string",
|
|
779
|
+
"description": "Regular expression matching the line that closes the block (this line is not kept)."
|
|
780
|
+
}
|
|
781
|
+
},
|
|
782
|
+
"additionalProperties": false,
|
|
783
|
+
"description": "Extracts the block of lines between a starting and an ending regular expression."
|
|
784
|
+
},
|
|
738
785
|
"css": {
|
|
739
786
|
"oneOf": [
|
|
740
787
|
{ "type": "string", "description": "CSS selector expression." },
|
|
@@ -182,7 +182,7 @@ class Headers(typing.MutableMapping[str, str]):
|
|
|
182
182
|
"""
|
|
183
183
|
return [(key.decode(self.encoding), value.decode(self.encoding)) for _, key, value in self._list]
|
|
184
184
|
|
|
185
|
-
def get(self, key: str, default: typing.Any = None) -> typing.Any:
|
|
185
|
+
def get(self, key: str, default: typing.Any = None) -> typing.Any: # ty:ignore[invalid-method-override]
|
|
186
186
|
"""
|
|
187
187
|
Return a header value. If multiple occurrences of the header occur
|
|
188
188
|
then concatenate them together with commas.
|