webchanges 3.38.0__tar.gz → 3.40.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.38.0/webchanges.egg-info → webchanges-3.40.0}/PKG-INFO +31 -29
- {webchanges-3.38.0 → webchanges-3.40.0}/README.rst +25 -23
- {webchanges-3.38.0 → webchanges-3.40.0}/pyproject.toml +49 -27
- {webchanges-3.38.0 → webchanges-3.40.0}/requirements.txt +1 -1
- {webchanges-3.38.0 → webchanges-3.40.0}/setup.py +5 -3
- {webchanges-3.38.0 → webchanges-3.40.0}/tools/get_manpages_parser.py +2 -1
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/__init__.py +5 -4
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/__main__.py +2 -0
- webchanges-3.40.0/webchanges/_httpx.py +37 -0
- webchanges-3.40.0/webchanges/_resources/.config.schema.sha256 +1 -0
- webchanges-3.40.0/webchanges/_resources/.jobs.schema.sha256 +1 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_resources/config.schema.json +78 -35
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_resources/jobs.schema.json +348 -170
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_vendored/headers.py +67 -37
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_vendored/packaging_version.py +4 -4
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_vendored/typeguard.py +1 -1
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/cli.py +307 -230
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/command.py +163 -84
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/config.py +28 -10
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/differs.py +735 -459
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_base.py +13 -12
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_document.py +15 -13
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_html.py +121 -29
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_shell.py +9 -4
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_text.py +35 -21
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/handler.py +43 -27
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/_base.py +240 -112
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/_browser.py +222 -256
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/_exceptions.py +11 -10
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/_shell.py +49 -11
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/_url.py +406 -401
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/mailer.py +14 -7
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/main.py +5 -5
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/__init__.py +3 -2
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_base.py +108 -59
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_browser.py +4 -4
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_chat.py +82 -47
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_email.py +13 -9
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_stdout.py +15 -10
- webchanges-3.40.0/webchanges/reporters/_system.py +136 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/reporters/_web.py +99 -64
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/__init__.py +2 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_base.py +12 -10
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_config.py +25 -5
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_redis.py +3 -2
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_sqlite3.py +18 -18
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_ssdb.py +9 -5
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_yaml.py +84 -33
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/util.py +138 -17
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/worker.py +153 -118
- {webchanges-3.38.0 → webchanges-3.40.0/webchanges.egg-info}/PKG-INFO +31 -29
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges.egg-info/SOURCES.txt +3 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges.egg-info/requires.txt +6 -6
- webchanges-3.38.0/webchanges/reporters/_system.py +0 -71
- {webchanges-3.38.0 → webchanges-3.40.0}/LICENSE.md +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/MANIFEST.in +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/setup.cfg +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_resources/__init__.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/_vendored/__init__.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/__init__.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/filters/_encoding.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/jobs/__init__.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/py.typed +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage/_minidb.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges/storage_minidb.py +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges.egg-info/dependency_links.txt +0 -0
- {webchanges-3.38.0 → webchanges-3.40.0}/webchanges.egg-info/entry_points.txt +0 -0
- {webchanges-3.38.0 → webchanges-3.40.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.40.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>
|
|
@@ -40,7 +40,7 @@ License-File: LICENSE.md
|
|
|
40
40
|
Requires-Dist: cssselect
|
|
41
41
|
Requires-Dist: h2
|
|
42
42
|
Requires-Dist: html2text
|
|
43
|
-
Requires-Dist:
|
|
43
|
+
Requires-Dist: httpx2
|
|
44
44
|
Requires-Dist: lxml
|
|
45
45
|
Requires-Dist: markdown2
|
|
46
46
|
Requires-Dist: msgpack
|
|
@@ -77,11 +77,11 @@ Requires-Dist: cryptography; extra == "pypdf-crypto"
|
|
|
77
77
|
Provides-Extra: xmltodict
|
|
78
78
|
Requires-Dist: xmltodict; extra == "xmltodict"
|
|
79
79
|
Provides-Extra: deepdiff
|
|
80
|
-
Requires-Dist: deepdiff
|
|
81
|
-
Requires-Dist: deepdiff<9
|
|
80
|
+
Requires-Dist: deepdiff; python_version < "3.15" and extra == "deepdiff"
|
|
81
|
+
Requires-Dist: deepdiff<9.1; python_version >= "3.15" and extra == "deepdiff"
|
|
82
82
|
Provides-Extra: deepdiff-xml
|
|
83
|
-
Requires-Dist: deepdiff
|
|
84
|
-
Requires-Dist: deepdiff<9
|
|
83
|
+
Requires-Dist: deepdiff; python_version < "3.15" and extra == "deepdiff-xml"
|
|
84
|
+
Requires-Dist: deepdiff<9.1; python_version >= "3.15" and extra == "deepdiff-xml"
|
|
85
85
|
Requires-Dist: xmltodict; extra == "deepdiff-xml"
|
|
86
86
|
Provides-Extra: imagediff
|
|
87
87
|
Requires-Dist: Pillow; extra == "imagediff"
|
|
@@ -92,7 +92,7 @@ Requires-Dist: pushbullet.py; extra == "pushbullet"
|
|
|
92
92
|
Provides-Extra: pushover
|
|
93
93
|
Requires-Dist: chump; extra == "pushover"
|
|
94
94
|
Provides-Extra: xmpp
|
|
95
|
-
Requires-Dist:
|
|
95
|
+
Requires-Dist: slixmpp; extra == "xmpp"
|
|
96
96
|
Provides-Extra: curl-cffi
|
|
97
97
|
Requires-Dist: curl_cffi; extra == "curl-cffi"
|
|
98
98
|
Provides-Extra: redis
|
|
@@ -123,22 +123,25 @@ notifications and AI-powered summaries to your favorite `platform
|
|
|
123
123
|
|
|
124
124
|
Highlights
|
|
125
125
|
==========
|
|
126
|
-
- **
|
|
127
|
-
<https://webchanges.readthedocs.io/en/stable/
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- **
|
|
131
|
-
<https://webchanges.readthedocs.io/en/stable/differs.html#
|
|
132
|
-
- **
|
|
133
|
-
<https://webchanges.readthedocs.io/en/stable/
|
|
134
|
-
- **
|
|
126
|
+
- **Watch anything**: web pages (in a `real browser
|
|
127
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#use-browser>`__ if needed), APIs, local files and command
|
|
128
|
+
output.
|
|
129
|
+
- **Track only what matters** with over 30 `filters <https://webchanges.readthedocs.io/en/stable/filters.html>`__.
|
|
130
|
+
- **Read changes at a glance** in formatted HTML, side by side, word by word, as `AI summaries
|
|
131
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__ and more.
|
|
132
|
+
- **Get notified anywhere**: email, Telegram, Discord, ntfy, webhooks and `more
|
|
133
|
+
<https://webchanges.readthedocs.io/en/stable/reporters.html>`__.
|
|
134
|
+
- **Few false alarms**: transient errors can be held back and repeated ones reported `once
|
|
135
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#suppress-repeated-errors>`__.
|
|
136
|
+
- **Runs on your machine**, total privacy, no account needed, and extends with Python `hooks
|
|
137
|
+
<https://webchanges.readthedocs.io/en/stable/hooks.html>`__.
|
|
135
138
|
|
|
136
139
|
|
|
137
140
|
Requirements
|
|
138
141
|
============
|
|
139
142
|
**webchanges** requires |support|. For the best experience, use the current version of `Python
|
|
140
|
-
<https://www.python.org/downloads/>`__; older Python versions are supported for 3 years after they're replaced.
|
|
141
|
-
|
|
143
|
+
<https://www.python.org/downloads/>`__; older Python versions are supported for 3 years after they're replaced.
|
|
144
|
+
Free-threaded Python is supported.
|
|
142
145
|
|
|
143
146
|
For Generative AI summaries (BETA), you need a free `API Key from Google Cloud AI Studio
|
|
144
147
|
<https://aistudio.google.com/app/apikey>`__ (see `here
|
|
@@ -167,9 +170,10 @@ On Windows with Python 3.15, first run ``set PYYAML_FORCE_LIBYAML=0`` (in PowerS
|
|
|
167
170
|
|
|
168
171
|
Other ways to run
|
|
169
172
|
-----------------
|
|
170
|
-
- In a `Docker <https://www.docker.com/>`__ container: a
|
|
171
|
-
<https://github.com/yubiuser/webchanges-docker>`__
|
|
172
|
-
<https://github.com/jhedlund/webchanges-docker>`__
|
|
173
|
+
- In a `Docker <https://www.docker.com/>`__ container: download a third-party container, `yubiuser/webchanges-docker
|
|
174
|
+
<https://github.com/yubiuser/webchanges-docker>`__ (no browser) or `jhedlund/webchanges-docker
|
|
175
|
+
<https://github.com/jhedlund/webchanges-docker>`__ (with a browser), or adapt the tested `sample Dockerfile
|
|
176
|
+
<https://webchanges.readthedocs.io/en/stable/advanced.html#docker-sample>`__ (no browser).
|
|
173
177
|
- As a `GitHub Action <https://docs.github.com/en/actions>`__: an implementation is `here
|
|
174
178
|
<https://github.com/swimmwatch/webchanges-action>`__.
|
|
175
179
|
|
|
@@ -224,7 +228,7 @@ Schedule
|
|
|
224
228
|
|
|
225
229
|
Code
|
|
226
230
|
====
|
|
227
|
-
|coveralls| |issues| |code_style|
|
|
231
|
+
|coveralls| |issues| |code_style|
|
|
228
232
|
|
|
229
233
|
The code, issues tracker, and discussions are hosted on `GitHub <https://github.com/mborsetti/webchanges>`__.
|
|
230
234
|
|
|
@@ -243,10 +247,11 @@ License
|
|
|
243
247
|
=======
|
|
244
248
|
|license|
|
|
245
249
|
|
|
246
|
-
See the `complete licenses
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
licensed under a
|
|
250
|
+
See the `complete licenses
|
|
251
|
+
<https://raw.githubusercontent.com/mborsetti/webchanges/refs/heads/main/LICENSE.md>`__ (released under the `MIT
|
|
252
|
+
License <https://opensource.org/licenses/MIT>`__ but redistributing modified source code, dated 30 July 2020, from
|
|
253
|
+
`urlwatch 2.21 <https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ licensed under a
|
|
254
|
+
`BSD 3-Clause License
|
|
250
255
|
<https://raw.githubusercontent.com/thp/urlwatch/346b25914b0418342ffe2fb0529bed702fddc01f/COPYING>`__).
|
|
251
256
|
|
|
252
257
|
|
|
@@ -302,6 +307,3 @@ see the `comparison <https://webchanges.readthedocs.io/en/stable/upgrading.html>
|
|
|
302
307
|
.. .. |snyk| image:: https://snyk.io/advisor/python/webchanges/badge.svg
|
|
303
308
|
.. :target: https://security.snyk.io/package/pip/webchanges
|
|
304
309
|
.. :alt: Snyk Package Health Score
|
|
305
|
-
.. |OpenSSF_Scorecard| image:: https://api.scorecard.dev/projects/github.com/mborsetti/webchanges/badge
|
|
306
|
-
:target: https://scorecard.dev/viewer/?uri=github.com/mborsetti/webchanges
|
|
307
|
-
:alt: OpenSSF Scoreard
|
|
@@ -16,22 +16,25 @@ notifications and AI-powered summaries to your favorite `platform
|
|
|
16
16
|
|
|
17
17
|
Highlights
|
|
18
18
|
==========
|
|
19
|
-
- **
|
|
20
|
-
<https://webchanges.readthedocs.io/en/stable/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- **
|
|
24
|
-
<https://webchanges.readthedocs.io/en/stable/differs.html#
|
|
25
|
-
- **
|
|
26
|
-
<https://webchanges.readthedocs.io/en/stable/
|
|
27
|
-
- **
|
|
19
|
+
- **Watch anything**: web pages (in a `real browser
|
|
20
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#use-browser>`__ if needed), APIs, local files and command
|
|
21
|
+
output.
|
|
22
|
+
- **Track only what matters** with over 30 `filters <https://webchanges.readthedocs.io/en/stable/filters.html>`__.
|
|
23
|
+
- **Read changes at a glance** in formatted HTML, side by side, word by word, as `AI summaries
|
|
24
|
+
<https://webchanges.readthedocs.io/en/stable/differs.html#ai-google-diff>`__ and more.
|
|
25
|
+
- **Get notified anywhere**: email, Telegram, Discord, ntfy, webhooks and `more
|
|
26
|
+
<https://webchanges.readthedocs.io/en/stable/reporters.html>`__.
|
|
27
|
+
- **Few false alarms**: transient errors can be held back and repeated ones reported `once
|
|
28
|
+
<https://webchanges.readthedocs.io/en/stable/jobs.html#suppress-repeated-errors>`__.
|
|
29
|
+
- **Runs on your machine**, total privacy, no account needed, and extends with Python `hooks
|
|
30
|
+
<https://webchanges.readthedocs.io/en/stable/hooks.html>`__.
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
Requirements
|
|
31
34
|
============
|
|
32
35
|
**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.
|
|
34
|
-
|
|
36
|
+
<https://www.python.org/downloads/>`__; older Python versions are supported for 3 years after they're replaced.
|
|
37
|
+
Free-threaded Python is supported.
|
|
35
38
|
|
|
36
39
|
For Generative AI summaries (BETA), you need a free `API Key from Google Cloud AI Studio
|
|
37
40
|
<https://aistudio.google.com/app/apikey>`__ (see `here
|
|
@@ -60,9 +63,10 @@ On Windows with Python 3.15, first run ``set PYYAML_FORCE_LIBYAML=0`` (in PowerS
|
|
|
60
63
|
|
|
61
64
|
Other ways to run
|
|
62
65
|
-----------------
|
|
63
|
-
- In a `Docker <https://www.docker.com/>`__ container: a
|
|
64
|
-
<https://github.com/yubiuser/webchanges-docker>`__
|
|
65
|
-
<https://github.com/jhedlund/webchanges-docker>`__
|
|
66
|
+
- In a `Docker <https://www.docker.com/>`__ container: download a third-party container, `yubiuser/webchanges-docker
|
|
67
|
+
<https://github.com/yubiuser/webchanges-docker>`__ (no browser) or `jhedlund/webchanges-docker
|
|
68
|
+
<https://github.com/jhedlund/webchanges-docker>`__ (with a browser), or adapt the tested `sample Dockerfile
|
|
69
|
+
<https://webchanges.readthedocs.io/en/stable/advanced.html#docker-sample>`__ (no browser).
|
|
66
70
|
- As a `GitHub Action <https://docs.github.com/en/actions>`__: an implementation is `here
|
|
67
71
|
<https://github.com/swimmwatch/webchanges-action>`__.
|
|
68
72
|
|
|
@@ -117,7 +121,7 @@ Schedule
|
|
|
117
121
|
|
|
118
122
|
Code
|
|
119
123
|
====
|
|
120
|
-
|coveralls| |issues| |code_style|
|
|
124
|
+
|coveralls| |issues| |code_style|
|
|
121
125
|
|
|
122
126
|
The code, issues tracker, and discussions are hosted on `GitHub <https://github.com/mborsetti/webchanges>`__.
|
|
123
127
|
|
|
@@ -136,10 +140,11 @@ License
|
|
|
136
140
|
=======
|
|
137
141
|
|license|
|
|
138
142
|
|
|
139
|
-
See the `complete licenses
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
licensed under a
|
|
143
|
+
See the `complete licenses
|
|
144
|
+
<https://raw.githubusercontent.com/mborsetti/webchanges/refs/heads/main/LICENSE.md>`__ (released under the `MIT
|
|
145
|
+
License <https://opensource.org/licenses/MIT>`__ but redistributing modified source code, dated 30 July 2020, from
|
|
146
|
+
`urlwatch 2.21 <https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ licensed under a
|
|
147
|
+
`BSD 3-Clause License
|
|
143
148
|
<https://raw.githubusercontent.com/thp/urlwatch/346b25914b0418342ffe2fb0529bed702fddc01f/COPYING>`__).
|
|
144
149
|
|
|
145
150
|
|
|
@@ -194,7 +199,4 @@ see the `comparison <https://webchanges.readthedocs.io/en/stable/upgrading.html>
|
|
|
194
199
|
.. :alt: Security Status
|
|
195
200
|
.. .. |snyk| image:: https://snyk.io/advisor/python/webchanges/badge.svg
|
|
196
201
|
.. :target: https://security.snyk.io/package/pip/webchanges
|
|
197
|
-
.. :alt: Snyk Package Health Score
|
|
198
|
-
.. |OpenSSF_Scorecard| image:: https://api.scorecard.dev/projects/github.com/mborsetti/webchanges/badge
|
|
199
|
-
:target: https://scorecard.dev/viewer/?uri=github.com/mborsetti/webchanges
|
|
200
|
-
:alt: OpenSSF Scoreard
|
|
202
|
+
.. :alt: Snyk Package Health Score
|
|
@@ -77,13 +77,12 @@ pypdf = ['pypdf']
|
|
|
77
77
|
pypdf_crypto = ['pypdf', 'cryptography']
|
|
78
78
|
xmltodict = ['xmltodict'] # xmltojson and xmltoyaml filters
|
|
79
79
|
# differs
|
|
80
|
-
# deepdiff >=
|
|
81
|
-
# deepdiff < 9 on Python >= 3.15: deepdiff 9 requires cachebox < 6, and cachebox 5.x has no 3.15 wheels and cannot be
|
|
80
|
+
# deepdiff < 9.1 on Python >= 3.15: deepdiff 9.1 requires cachebox < 6, and cachebox 5.x has no 3.15 wheels and cannot be
|
|
82
81
|
# built for 3.15 (it uses PyO3 0.27, which supports Python only up to 3.14). Keep in sync with tests/requirements_*.txt
|
|
83
|
-
deepdiff = ['deepdiff
|
|
82
|
+
deepdiff = ['deepdiff; python_version < "3.15"', 'deepdiff < 9.1; python_version >= "3.15"']
|
|
84
83
|
deepdiff_xml = [
|
|
85
|
-
'deepdiff
|
|
86
|
-
'deepdiff
|
|
84
|
+
'deepdiff; python_version < "3.15"',
|
|
85
|
+
'deepdiff < 9.1; python_version >= "3.15"',
|
|
87
86
|
'xmltodict',
|
|
88
87
|
]
|
|
89
88
|
imagediff = ['Pillow']
|
|
@@ -91,7 +90,7 @@ imagediff = ['Pillow']
|
|
|
91
90
|
matrix = ['matrix_client']
|
|
92
91
|
pushbullet = ['pushbullet.py']
|
|
93
92
|
pushover = ['chump']
|
|
94
|
-
xmpp = ['
|
|
93
|
+
xmpp = ['slixmpp']
|
|
95
94
|
# other
|
|
96
95
|
curl_cffi = ['curl_cffi']
|
|
97
96
|
redis = ['redis']
|
|
@@ -126,7 +125,7 @@ dependencies = { file = 'requirements.txt' }
|
|
|
126
125
|
|
|
127
126
|
[tool.setuptools.package-data]
|
|
128
127
|
'webchanges' = ['py.typed']
|
|
129
|
-
'webchanges._resources' = ['*.schema.json', '
|
|
128
|
+
'webchanges._resources' = ['*.schema.json', '.*.schema.sha256'] # globs skip dotfiles unless the dot is explicit
|
|
130
129
|
|
|
131
130
|
# -------------------------- manpages --------------------------
|
|
132
131
|
# https://github.com/praiskup/argparse-manpage/blob/main/README.md
|
|
@@ -154,6 +153,7 @@ omit = [
|
|
|
154
153
|
'pip/*',
|
|
155
154
|
'tests/*',
|
|
156
155
|
'webchanges/_vendored/*',
|
|
156
|
+
'webchanges/storage/_redis.py',
|
|
157
157
|
'webchanges.egg-info/*',
|
|
158
158
|
]
|
|
159
159
|
relative_files = true
|
|
@@ -258,26 +258,43 @@ line-length = 120
|
|
|
258
258
|
# By default, Ruff enables Flake8's F rules, along with a subset of the E rules
|
|
259
259
|
# Enable rules not enabled by default, and ignore specific rules.
|
|
260
260
|
select = [
|
|
261
|
+
# 'AIR', # Airflow
|
|
262
|
+
# 'ERA', # eradicate
|
|
263
|
+
# 'FAST', # FastAPI
|
|
264
|
+
'YTT', # flake8-2020
|
|
261
265
|
'ANN', # flake8-annotations
|
|
266
|
+
'ASYNC', # flake8-async
|
|
262
267
|
'S', # flake8-bandit
|
|
263
268
|
'BLE', # flake8-blind-except
|
|
269
|
+
# 'FBT', # flake8-boolean-trap
|
|
264
270
|
'B', # flake8-bugbear
|
|
265
271
|
'A', # flake8-builtin
|
|
272
|
+
# 'COM', # flake8-commas
|
|
266
273
|
'C4', # flake8-comprehensions
|
|
274
|
+
# 'CPY', # flake8-copyright
|
|
267
275
|
'DTZ', # flake8-datetimez
|
|
268
|
-
# '
|
|
276
|
+
# 'T10', # flake8-debugger
|
|
277
|
+
# 'DJ', # flake8-django
|
|
278
|
+
# 'EM', # flake8-errmsg
|
|
279
|
+
# 'EXE', # flake8-executable
|
|
280
|
+
# 'FIX', # flake8-fixme
|
|
269
281
|
'FA', # flake8-future-annotations
|
|
270
282
|
'INT', # flake8-gettext
|
|
271
283
|
'ISC', # flake8-implicit-str-concat
|
|
284
|
+
'ICN', # flake8-import-conventions
|
|
272
285
|
'LOG', # flake8-logging
|
|
273
|
-
|
|
286
|
+
'G', # flake8-logging-format
|
|
287
|
+
# 'INP', # flake8-no-pep420
|
|
274
288
|
'PIE', # flake8-pie
|
|
289
|
+
# 'T20', # flake8-print
|
|
275
290
|
'PYI', # flake8-pyi
|
|
276
291
|
'PT', # flake8-pytest-style
|
|
277
292
|
'Q', # flake8-quotes
|
|
278
293
|
'RSE', # flake8-raise
|
|
279
294
|
'RET', # flake8-return
|
|
295
|
+
# 'SLF', # flake8-self
|
|
280
296
|
'SIM', # flake8-simplify
|
|
297
|
+
'SLOT', # flake8-slots
|
|
281
298
|
'TID', # flake8-tidy-imports
|
|
282
299
|
'TD', # flake8-todos
|
|
283
300
|
'TC', # flake8-type-checking
|
|
@@ -286,29 +303,31 @@ select = [
|
|
|
286
303
|
'FLY', # flynt
|
|
287
304
|
'I', # isort
|
|
288
305
|
'C90', # mccabe
|
|
306
|
+
# 'NPY', # NumPy-specific rules
|
|
307
|
+
# 'PD', # pandas-vet
|
|
289
308
|
'N', # pep8-naming
|
|
290
309
|
'PERF', # Perflint
|
|
291
310
|
'E', # pycodestyle errors
|
|
292
311
|
'W', # pycodestyle warnings
|
|
293
|
-
# 'DOC', # pydoclint
|
|
294
|
-
|
|
312
|
+
# 'DOC', # pydoclint (requires enabling preview, which turns on a TON of other stuff)
|
|
313
|
+
'D', # pydocstyle
|
|
295
314
|
'F', # Pyflakes
|
|
315
|
+
# 'PGH', # pygrep-hooks
|
|
296
316
|
# 'PL', # Pylint # TODO
|
|
317
|
+
'UP', # pyupgrade
|
|
297
318
|
'FURB', # refurb
|
|
298
319
|
'RUF', # Ruff-specific rules
|
|
299
320
|
# 'TRY', # tryceratops # TODO
|
|
300
321
|
]
|
|
301
322
|
|
|
302
323
|
ignore = [
|
|
303
|
-
'
|
|
304
|
-
|
|
305
|
-
|
|
324
|
+
'D107', # Missing docstring in __init__. Class-level docstring (D101) already covers the object's purpose.
|
|
325
|
+
'D203', # Conflicts with D211, which forbids a blank line before a class docstring).
|
|
326
|
+
'D213', # Conflicts with D212, which says multi-line docstring summary should start on the first line (Google style).
|
|
306
327
|
'PLC0415', # `import` should be at the top-level of a file
|
|
307
|
-
'PT011', # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception
|
|
308
328
|
'PT030', # pytest.warns({warning}) is too broad, set the match parameter or use a more specific warning
|
|
309
329
|
'RUF012', # Mutable class attributes should be annotated with `typing.ClassVar`
|
|
310
330
|
'SIM105', # Use contextlib.suppress({exception}) instead of try-except-pass
|
|
311
|
-
'SIM115', # Use a context manager for opening files
|
|
312
331
|
'TD002', # Missing author in TODO
|
|
313
332
|
'TD003', # Missing issue link for this TODO
|
|
314
333
|
]
|
|
@@ -324,18 +343,24 @@ dummy-variable-rgx = '^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$'
|
|
|
324
343
|
allowed-confusables = ['–', '‘', '’']
|
|
325
344
|
|
|
326
345
|
[tool.ruff.lint.flake8-annotations]
|
|
327
|
-
allow-star-arg-any = true
|
|
346
|
+
allow-star-arg-any = true
|
|
328
347
|
|
|
329
348
|
[tool.ruff.lint.flake8-quotes]
|
|
330
349
|
inline-quotes = 'single'
|
|
331
350
|
|
|
332
351
|
[tool.ruff.lint.mccabe]
|
|
333
352
|
# Flag errors (`C901`) whenever the complexity level exceeds below.
|
|
334
|
-
max-complexity =
|
|
353
|
+
max-complexity = 20 # 10 is default, 13 to 15 is modern practice
|
|
335
354
|
|
|
336
355
|
[tool.ruff.lint.per-file-ignores]
|
|
337
|
-
'tests
|
|
356
|
+
'{tests/**,tools/test_*}' = [
|
|
357
|
+
'ANN401', # Dynamically typed expressions (typing.Any) are disallowed
|
|
358
|
+
'PT011', # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception
|
|
338
359
|
'S101', # Use of `assert` detected
|
|
360
|
+
# Test functions are self-documenting:
|
|
361
|
+
'D101', # Missing docstring in public class
|
|
362
|
+
'D102', # Missing docstring in public method
|
|
363
|
+
'D103', # Missing docstring in public function
|
|
339
364
|
]
|
|
340
365
|
|
|
341
366
|
[tool.ruff.lint.pydoclint]
|
|
@@ -382,14 +407,11 @@ docstring-code-line-length = 'dynamic'
|
|
|
382
407
|
# -------------------------- ty --------------------------
|
|
383
408
|
# Config file documentation at https://docs.astral.sh/ty/reference/configuration/
|
|
384
409
|
|
|
410
|
+
# A ty.toml (e.g. one adding machine-specific interpreter paths) replaces this section entirely, so keep its other
|
|
411
|
+
# settings the same as here. 'tools' is needed to resolve the scripts there that tests import after adding the
|
|
412
|
+
# directory to sys.path at runtime (e.g. update_schema_hashes in tests/test_cli.py), which ty cannot follow.
|
|
385
413
|
[tool.ty.environment]
|
|
386
|
-
extra-paths = ['webchanges']
|
|
414
|
+
extra-paths = ['webchanges', 'tools']
|
|
387
415
|
|
|
388
416
|
[tool.ty.src]
|
|
389
|
-
exclude = ["./webchanges/.**", "./webchanges/
|
|
390
|
-
|
|
391
|
-
[[tool.ty.overrides]]
|
|
392
|
-
include = ["./webchanges/storage/_minidb.py"]
|
|
393
|
-
|
|
394
|
-
[tool.ty.overrides.rules]
|
|
395
|
-
all = "ignore"
|
|
417
|
+
exclude = ["./webchanges/.**", "./webchanges/storage/_minidb.py"]
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"""Shim wiring argparse-manpage's ``build_manpages`` cmdclass into setuptools.
|
|
2
|
+
|
|
3
|
+
All other configuration lives in pyproject.toml. See https://github.com/praiskup/argparse-manpage/blob/main/README.md
|
|
4
|
+
"""
|
|
5
|
+
|
|
4
6
|
from __future__ import annotations
|
|
5
7
|
|
|
6
8
|
from build_manpages import build_manpages, get_build_py_cmd, get_install_cmd
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Expose webchanges' argument parser to argparse-manpage."""
|
|
2
|
+
|
|
1
3
|
from __future__ import annotations
|
|
2
4
|
|
|
3
5
|
import sys
|
|
@@ -18,6 +20,5 @@ def get_manpages_parser() -> ArgumentParser:
|
|
|
18
20
|
|
|
19
21
|
https://github.com/praiskup/argparse-manpage/blob/main/README.md
|
|
20
22
|
"""
|
|
21
|
-
|
|
22
23
|
null_path = Path()
|
|
23
24
|
return CommandConfig([], null_path, null_path, null_path, null_path, null_path).parse_args([])
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
"""Checks web content, including images, to detect any changes since the prior run.
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"""Checks web content, including images, to detect any changes since the prior run.
|
|
2
|
+
|
|
3
|
+
If any are found, it summarizes (including with Gen AI) what changed ('diff') and displays it and/or sends it via email
|
|
4
|
+
and/or other supported services. Can check the output of local commands as well.
|
|
4
5
|
"""
|
|
5
6
|
|
|
6
7
|
# The code below is subject to the license contained in the LICENSE.md file, which is part of the source code.
|
|
@@ -22,7 +23,7 @@ __project_name__ = str(__package__)
|
|
|
22
23
|
# * MINOR version when you add functionality in a backwards compatible manner, and
|
|
23
24
|
# * MICRO or PATCH version when you make backwards compatible bug fixes. We no longer use '0'
|
|
24
25
|
# If unsure on increments, use pkg_resources.parse_version to parse
|
|
25
|
-
__version__ = '3.
|
|
26
|
+
__version__ = '3.40.0'
|
|
26
27
|
__description__ = (
|
|
27
28
|
'Check web (or command output) for changes since last run and notify.\n\nAnonymously alerts you of web changes.'
|
|
28
29
|
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""The primary HTTP client: ``httpx2``, else ``httpx`` (same API) imported as ``httpx2``, else ``None``.
|
|
2
|
+
|
|
3
|
+
Modules get the client from here (``from webchanges._httpx import httpx2``) so that the choice is made in one place.
|
|
4
|
+
If neither is installed, ``requests`` and then ``curl_cffi`` are used instead (see ``UrlJob._select_http_client()`` in
|
|
5
|
+
``webchanges/jobs/_url.py``), so every use of ``httpx2`` must be guarded with ``if httpx2 is None`` / ``if httpx2``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# The code below is subject to the license contained in the LICENSE.md file, which is part of the source code.
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
__all__ = ['Headers', 'h2', 'httpx2']
|
|
15
|
+
|
|
16
|
+
# The fallback assignments below are hidden from the type checker behind `if not TYPE_CHECKING`. Otherwise the type
|
|
17
|
+
# checker infers the union of all bindings (e.g. `<module 'httpx2'> | None`), and every reference to a module
|
|
18
|
+
# attribute — including in annotations such as `httpx2.Response`, which cannot be guarded at runtime — is reported as
|
|
19
|
+
# unresolved. Hiding the fallbacks keeps the httpx2 module type, which is what these code paths are guarded to run
|
|
20
|
+
# under.
|
|
21
|
+
try:
|
|
22
|
+
import httpx2
|
|
23
|
+
from httpx2 import Headers
|
|
24
|
+
except ImportError: # pragma: no cover
|
|
25
|
+
if not TYPE_CHECKING:
|
|
26
|
+
try:
|
|
27
|
+
import httpx as httpx2
|
|
28
|
+
from httpx import Headers
|
|
29
|
+
except ImportError:
|
|
30
|
+
httpx2 = None
|
|
31
|
+
from webchanges._vendored.headers import Headers
|
|
32
|
+
|
|
33
|
+
# HTTP/2 support (used only by the client above).
|
|
34
|
+
try:
|
|
35
|
+
import h2
|
|
36
|
+
except ImportError: # pragma: no cover
|
|
37
|
+
h2 = None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
314f226aa22b4e546970df26dc47aa9bbd4ae170c67fabe9610f040f2d3f345e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
5b3c2a1db96278aefcb4a20acf1442a321b9c5c84711da1dc1751ca714a0d8ea
|