webchanges 3.33.0__tar.gz → 3.34.1__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.33.0/webchanges.egg-info → webchanges-3.34.1}/PKG-INFO +7 -69
- {webchanges-3.33.0 → webchanges-3.34.1}/README.rst +5 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/pyproject.toml +10 -10
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/__init__.py +1 -1
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/_vendored/headers.py +1 -1
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/command.py +27 -30
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/config.py +1 -2
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/differs.py +311 -166
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/handler.py +43 -26
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/main.py +7 -1
- webchanges-3.34.1/webchanges/storage_minidb.py +7 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/util.py +13 -6
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/worker.py +12 -9
- {webchanges-3.33.0 → webchanges-3.34.1/webchanges.egg-info}/PKG-INFO +7 -69
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges.egg-info/SOURCES.txt +0 -4
- webchanges-3.33.0/webchanges/filters.py +0 -1824
- webchanges-3.33.0/webchanges/jobs.py +0 -2149
- webchanges-3.33.0/webchanges/reporters.py +0 -1930
- webchanges-3.33.0/webchanges/storage.py +0 -1940
- webchanges-3.33.0/webchanges/storage_minidb.py +0 -170
- {webchanges-3.33.0 → webchanges-3.34.1}/LICENSE.md +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/MANIFEST.in +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/requirements.txt +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/setup.cfg +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/__main__.py +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/_vendored/__init__.py +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/_vendored/packaging_version.py +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/cli.py +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/mailer.py +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges/py.typed +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges.egg-info/dependency_links.txt +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges.egg-info/entry_points.txt +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges.egg-info/requires.txt +0 -0
- {webchanges-3.33.0 → webchanges-3.34.1}/webchanges.egg-info/top_level.txt +0 -0
|
@@ -1,75 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webchanges
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.34.1
|
|
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>
|
|
7
|
-
License:
|
|
8
|
-
Licenses
|
|
9
|
-
========
|
|
10
|
-
|
|
11
|
-
The MIT License (MIT)
|
|
12
|
-
|
|
13
|
-
Copyright (c) 2020- Mike Borsetti <mike@borsetti.com>
|
|
14
|
-
|
|
15
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
16
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
17
|
-
the Software without restriction, including without limitation the rights to
|
|
18
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
19
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
20
|
-
subject to the following conditions:
|
|
21
|
-
|
|
22
|
-
The above copyright notice and this permission notice shall be included in all
|
|
23
|
-
copies or substantial portions of the Software.
|
|
24
|
-
|
|
25
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
27
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
28
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
29
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
30
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
31
|
-
|
|
32
|
-
--------------------------------------------------------------------------------
|
|
33
|
-
|
|
34
|
-
SOURCE CODE REDISTRIBUTION NOTICE
|
|
35
|
-
(urlwatch by Thomas Perl)
|
|
36
|
-
|
|
37
|
-
This software redistributes source code of release 2.21, dated 30 July 2020, of
|
|
38
|
-
urlwatch
|
|
39
|
-
https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f,
|
|
40
|
-
which is subject to the following copyright notice and license (from
|
|
41
|
-
https://raw.githubusercontent.com/thp/urlwatch/346b25914b0418342ffe2fb0529bed702fddc01f/COPYING),
|
|
42
|
-
hereby retained and redistributed with the source code (of which this license
|
|
43
|
-
file is part of), in binary form, and in the documentation. The appearance of
|
|
44
|
-
the name of the author below does not constitute an endorsement or promotion of
|
|
45
|
-
this software by such author.
|
|
46
|
-
|
|
47
|
-
Copyright (c) 2008-2020 Thomas Perl <m@thp.io>
|
|
48
|
-
All rights reserved.
|
|
49
|
-
|
|
50
|
-
Redistribution and use in source and binary forms, with or without
|
|
51
|
-
modification, are permitted provided that the following conditions
|
|
52
|
-
are met:
|
|
53
|
-
|
|
54
|
-
1. Redistributions of source code must retain the above copyright
|
|
55
|
-
notice, this list of conditions and the following disclaimer.
|
|
56
|
-
2. Redistributions in binary form must reproduce the above copyright
|
|
57
|
-
notice, this list of conditions and the following disclaimer in the
|
|
58
|
-
documentation and/or other materials provided with the distribution.
|
|
59
|
-
3. The name of the author may not be used to endorse or promote products
|
|
60
|
-
derived from this software without specific prior written permission.
|
|
61
|
-
|
|
62
|
-
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
|
63
|
-
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
64
|
-
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
65
|
-
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
66
|
-
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
67
|
-
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
68
|
-
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
69
|
-
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
70
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
71
|
-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
72
|
-
|
|
7
|
+
License-Expression: MIT AND BSD-3-Clause
|
|
73
8
|
Project-URL: Documentation, https://webchanges.readthedocs.io/
|
|
74
9
|
Project-URL: Repository, https://github.com/mborsetti/webchanges/
|
|
75
10
|
Project-URL: Changelog, https://webchanges.readthedocs.io/en/stable/changelog.html
|
|
@@ -81,8 +16,6 @@ Classifier: Environment :: Console
|
|
|
81
16
|
Classifier: Intended Audience :: Developers
|
|
82
17
|
Classifier: Intended Audience :: End Users/Desktop
|
|
83
18
|
Classifier: Intended Audience :: System Administrators
|
|
84
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
85
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
86
19
|
Classifier: Natural Language :: English
|
|
87
20
|
Classifier: Operating System :: OS Independent
|
|
88
21
|
Classifier: Programming Language :: Python
|
|
@@ -219,6 +152,11 @@ Running in Docker
|
|
|
219
152
|
implementation (no browser) `here <https://github.com/yubiuser/webchanges-docker>`__, and one with a browser
|
|
220
153
|
`here <https://github.com/jhedlund/webchanges-docker>`__.
|
|
221
154
|
|
|
155
|
+
As a GitHub Action
|
|
156
|
+
------------------
|
|
157
|
+
**webchanges** can easily run as a `GitHub Action <https://www.docker.com/>`__! You will find an implementation
|
|
158
|
+
`here <https://github.com/swimmwatch/webchanges-action>`__.
|
|
159
|
+
|
|
222
160
|
|
|
223
161
|
Documentation |readthedocs|
|
|
224
162
|
===========================
|
|
@@ -51,6 +51,11 @@ Running in Docker
|
|
|
51
51
|
implementation (no browser) `here <https://github.com/yubiuser/webchanges-docker>`__, and one with a browser
|
|
52
52
|
`here <https://github.com/jhedlund/webchanges-docker>`__.
|
|
53
53
|
|
|
54
|
+
As a GitHub Action
|
|
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>`__.
|
|
58
|
+
|
|
54
59
|
|
|
55
60
|
Documentation |readthedocs|
|
|
56
61
|
===========================
|
|
@@ -17,7 +17,8 @@ name = 'webchanges'
|
|
|
17
17
|
description = 'Web Changes Delivered. AI-Summarized. Totally Anonymous.'
|
|
18
18
|
readme = { file = 'README.rst', content-type = 'text/x-rst' }
|
|
19
19
|
requires-python = '>=3.11'
|
|
20
|
-
license =
|
|
20
|
+
license = "MIT AND BSD-3-Clause"
|
|
21
|
+
license-files = ['LICENSE.md']
|
|
21
22
|
authors = [{ name = 'Mike Borsetti', email = 'mike+webchanges@borsetti.com' }]
|
|
22
23
|
maintainers = [
|
|
23
24
|
{ name = 'Mike Borsetti', email = 'mike+webchanges@borsetti.com' },
|
|
@@ -29,8 +30,6 @@ classifiers = [
|
|
|
29
30
|
'Intended Audience :: Developers',
|
|
30
31
|
'Intended Audience :: End Users/Desktop',
|
|
31
32
|
'Intended Audience :: System Administrators',
|
|
32
|
-
'License :: OSI Approved :: BSD License',
|
|
33
|
-
'License :: OSI Approved :: MIT License',
|
|
34
33
|
'Natural Language :: English',
|
|
35
34
|
'Operating System :: OS Independent',
|
|
36
35
|
'Programming Language :: Python',
|
|
@@ -213,7 +212,7 @@ testpaths = ['tests']
|
|
|
213
212
|
# Config file documentation at https://docs.astral.sh/ruff/configuration/ and https://docs.astral.sh/ruff/settings/
|
|
214
213
|
|
|
215
214
|
# File patterns to omit from formatting and linting, in addition to those specified by exclude.
|
|
216
|
-
extend-exclude = ['webchanges/storage_minidb.py', 'webchanges/_vendored']
|
|
215
|
+
extend-exclude = ['webchanges/storage_minidb.py', 'webchanges/storage/_minidb.py', 'webchanges/_vendored']
|
|
217
216
|
|
|
218
217
|
# By default, Ruff will discover files matching *.py, *.pyi, *.ipynb, or pyproject.toml.
|
|
219
218
|
# Include additional files
|
|
@@ -256,7 +255,7 @@ select = [
|
|
|
256
255
|
'PTH', # flake8-use-pathlib
|
|
257
256
|
'FLY', # flynt
|
|
258
257
|
'I', # isort
|
|
259
|
-
'C90', # mccabe
|
|
258
|
+
'C90', # mccabe
|
|
260
259
|
'N', # pep8-naming
|
|
261
260
|
'PERF', # Perflint
|
|
262
261
|
'E', # pycodestyle errors
|
|
@@ -265,7 +264,7 @@ select = [
|
|
|
265
264
|
# 'D', # pydocstyle # TODO
|
|
266
265
|
'F', # Pyflakes
|
|
267
266
|
# 'PL', # Pylint # TODO
|
|
268
|
-
'FURB', # refurb
|
|
267
|
+
'FURB', # refurb
|
|
269
268
|
'RUF', # Ruff-specific rules
|
|
270
269
|
# 'TRY', # tryceratops # TODO
|
|
271
270
|
]
|
|
@@ -291,6 +290,9 @@ unfixable = []
|
|
|
291
290
|
# Allow unused variables when underscore-prefixed.
|
|
292
291
|
dummy-variable-rgx = '^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$'
|
|
293
292
|
|
|
293
|
+
# List of allowed 'confusable' Unicode characters to ignore when enforcing RUF001, RUF002, and RUF003.
|
|
294
|
+
allowed-confusables = ['–', '‘', '’']
|
|
295
|
+
|
|
294
296
|
[tool.ruff.lint.flake8-annotations]
|
|
295
297
|
allow-star-arg-any = true # TODO
|
|
296
298
|
|
|
@@ -346,11 +348,9 @@ docstring-code-format = true
|
|
|
346
348
|
# enabled.
|
|
347
349
|
docstring-code-line-length = 'dynamic'
|
|
348
350
|
|
|
351
|
+
|
|
349
352
|
# -------------------------- ty --------------------------
|
|
350
353
|
# Config file documentation at https://docs.astral.sh/ty/reference/configuration/
|
|
351
354
|
|
|
352
355
|
[tool.ty.environment]
|
|
353
|
-
extra-paths = ['
|
|
354
|
-
|
|
355
|
-
[tool.ty.src]
|
|
356
|
-
exclude = ['./webchanges/storage_minidb.py']
|
|
356
|
+
extra-paths = ['webchanges', 'webchanges/storage/_sqlite3.py']
|
|
@@ -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.34.1'
|
|
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
|
)
|
|
@@ -82,7 +82,7 @@ def _obfuscate_sensitive_headers(
|
|
|
82
82
|
) -> typing.Iterator[tuple[typing.AnyStr, typing.AnyStr]]:
|
|
83
83
|
for k, v in items:
|
|
84
84
|
if to_str(k.lower()) in SENSITIVE_HEADERS: # ty:ignore[no-matching-overload, invalid-argument-type]
|
|
85
|
-
v = to_bytes_or_str('[secure]', match_type_of=v)
|
|
85
|
+
v = to_bytes_or_str('[secure]', match_type_of=v)
|
|
86
86
|
yield k, v
|
|
87
87
|
|
|
88
88
|
|
|
@@ -51,7 +51,7 @@ if httpx is not None:
|
|
|
51
51
|
|
|
52
52
|
if TYPE_CHECKING:
|
|
53
53
|
from webchanges.main import Urlwatch
|
|
54
|
-
from webchanges.reporters import _ConfigReportersList
|
|
54
|
+
from webchanges.reporters._base import _ConfigReportersList
|
|
55
55
|
from webchanges.storage import _ConfigReportEmail, _ConfigReportEmailSmtp, _ConfigReportTelegram, _ConfigReportXmpp
|
|
56
56
|
|
|
57
57
|
logger = logging.getLogger(__name__)
|
|
@@ -64,16 +64,17 @@ class UrlwatchCommand:
|
|
|
64
64
|
self.urlwatcher = urlwatcher
|
|
65
65
|
self.urlwatch_config = urlwatcher.urlwatch_config
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
def _exit(arg: str | int | None) -> None:
|
|
67
|
+
def _exit(self, arg: str | int | None) -> None:
|
|
69
68
|
logger.info(f'Exiting with exit code {arg}')
|
|
69
|
+
|
|
70
|
+
self.urlwatcher.ssdb_storage.close()
|
|
70
71
|
sys.exit(arg)
|
|
71
72
|
|
|
72
73
|
def jobs_from_joblist(self) -> Iterator[JobBase]:
|
|
73
74
|
"""Generates the jobs to process from the joblist entered in the CLI."""
|
|
74
75
|
if self.urlwatcher.urlwatch_config.joblist:
|
|
75
|
-
jobs =
|
|
76
|
-
enabled_jobs =
|
|
76
|
+
jobs = [self._find_job(job_entry) for job_entry in self.urlwatcher.urlwatch_config.joblist]
|
|
77
|
+
enabled_jobs = [job for job in jobs if job.is_enabled()]
|
|
77
78
|
disabled = len(enabled_jobs) - len(jobs)
|
|
78
79
|
disabled_str = f' (excluding {disabled} disabled)' if disabled else ''
|
|
79
80
|
logger.debug(
|
|
@@ -81,7 +82,7 @@ class UrlwatchCommand:
|
|
|
81
82
|
f'command line: {", ".join(str(j) for j in self.urlwatcher.urlwatch_config.joblist)}'
|
|
82
83
|
)
|
|
83
84
|
else:
|
|
84
|
-
enabled_jobs =
|
|
85
|
+
enabled_jobs = [job for job in self.urlwatcher.jobs if job.is_enabled()]
|
|
85
86
|
disabled = len(enabled_jobs) - len(self.urlwatcher.jobs)
|
|
86
87
|
disabled_str = f' (excluding {disabled} disabled)' if disabled else ''
|
|
87
88
|
logger.debug(f'Processing {len(enabled_jobs)} job{"s" if enabled_jobs else ""}{disabled_str}')
|
|
@@ -308,7 +309,7 @@ class UrlwatchCommand:
|
|
|
308
309
|
print()
|
|
309
310
|
print('Installed dpkg dependencies:')
|
|
310
311
|
try:
|
|
311
|
-
import apt
|
|
312
|
+
import apt
|
|
312
313
|
|
|
313
314
|
apt_cache = apt.Cache()
|
|
314
315
|
|
|
@@ -500,24 +501,23 @@ class UrlwatchCommand:
|
|
|
500
501
|
|
|
501
502
|
def prepare_jobs(self) -> None:
|
|
502
503
|
"""Runs jobs that have no history to populate the snapshot database when they're newly added."""
|
|
503
|
-
new_jobs =
|
|
504
|
+
new_jobs = []
|
|
504
505
|
for idx, job in enumerate(self.urlwatcher.jobs):
|
|
505
506
|
has_history = bool(self.urlwatcher.ssdb_storage.get_history_snapshots(job.guid))
|
|
506
507
|
if not has_history:
|
|
507
508
|
print(f'Running new {job.get_indexed_location()}.')
|
|
508
|
-
new_jobs.
|
|
509
|
+
new_jobs.append(idx + 1)
|
|
509
510
|
if not new_jobs and not self.urlwatch_config.joblist:
|
|
510
511
|
print('Found no new jobs to run.')
|
|
511
512
|
return
|
|
512
|
-
self.urlwatcher.urlwatch_config.joblist =
|
|
513
|
+
self.urlwatcher.urlwatch_config.joblist = list(self.urlwatcher.urlwatch_config.joblist) + new_jobs
|
|
513
514
|
self.urlwatcher.run_jobs()
|
|
514
|
-
self.urlwatcher.close()
|
|
515
515
|
return
|
|
516
516
|
|
|
517
517
|
def test_differ(self, arg_test_differ: list[str]) -> int:
|
|
518
518
|
"""Runs diffs for a job on all the saved snapshots.
|
|
519
519
|
|
|
520
|
-
Outputs the result to stdout or the reporter selected
|
|
520
|
+
Outputs the result to stdout or the reporter selected with --test-reporter.
|
|
521
521
|
|
|
522
522
|
:param arg_test_differ: Either the job_id or a list containing [job_id, max_diffs]
|
|
523
523
|
:return: 1 if error, 0 if successful.
|
|
@@ -566,7 +566,7 @@ class UrlwatchCommand:
|
|
|
566
566
|
str(job_state.new_data),
|
|
567
567
|
history_dic_snapshots.keys(),
|
|
568
568
|
n=1,
|
|
569
|
-
) # ty:ignore[
|
|
569
|
+
) # ty:ignore[invalid-assignment]
|
|
570
570
|
if close_matches:
|
|
571
571
|
job_state.old_data = close_matches[0]
|
|
572
572
|
job_state.old_timestamp = history_dic_snapshots[close_matches[0]].timestamp
|
|
@@ -673,6 +673,7 @@ class UrlwatchCommand:
|
|
|
673
673
|
"""
|
|
674
674
|
executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
675
675
|
|
|
676
|
+
job_state: JobState
|
|
676
677
|
for job_state in executor.map(
|
|
677
678
|
lambda jobstate: jobstate.process(headless=not self.urlwatch_config.no_headless),
|
|
678
679
|
(stack.enter_context(JobState(self.urlwatcher.ssdb_storage, job)) for job in jobs),
|
|
@@ -706,7 +707,7 @@ class UrlwatchCommand:
|
|
|
706
707
|
|
|
707
708
|
with ExitStack() as stack:
|
|
708
709
|
# This code is from worker.run_jobs, modified to yield from job_runner.
|
|
709
|
-
from webchanges.worker import
|
|
710
|
+
from webchanges.worker import get_virt_mem_mib # avoid circular imports
|
|
710
711
|
|
|
711
712
|
# run non-BrowserJob jobs first
|
|
712
713
|
jobs_to_run = [job for job in jobs if not job.__is_browser__]
|
|
@@ -723,11 +724,12 @@ class UrlwatchCommand:
|
|
|
723
724
|
jobs_to_run = [job for job in jobs if job.__is_browser__]
|
|
724
725
|
if jobs_to_run:
|
|
725
726
|
gc.collect()
|
|
726
|
-
virt_mem =
|
|
727
|
+
virt_mem = get_virt_mem_mib() # in MiB
|
|
728
|
+
virt_mem = virt_mem * 0.85 # reserve 15% for misc. overhead
|
|
727
729
|
if self.urlwatch_config.max_workers:
|
|
728
730
|
max_workers = self.urlwatch_config.max_workers
|
|
729
731
|
else:
|
|
730
|
-
max_workers = max(int(virt_mem /
|
|
732
|
+
max_workers = max(int(virt_mem / 800), 1)
|
|
731
733
|
max_workers = min(max_workers, os.cpu_count() or 1)
|
|
732
734
|
logger.debug(
|
|
733
735
|
f"Running jobs that require Chrome (i.e. with 'use_browser: true') in parallel with "
|
|
@@ -866,7 +868,6 @@ class UrlwatchCommand:
|
|
|
866
868
|
count = self.urlwatcher.ssdb_storage.rollback(dt.timestamp())
|
|
867
869
|
if count:
|
|
868
870
|
print(f'Deleted {count} snapshots taken after {timestamp_date}.')
|
|
869
|
-
self.urlwatcher.ssdb_storage.close()
|
|
870
871
|
else:
|
|
871
872
|
print(f'No snapshots found after {timestamp_date}')
|
|
872
873
|
return 0
|
|
@@ -931,7 +932,7 @@ class UrlwatchCommand:
|
|
|
931
932
|
items2 = [(k, v) for k, v in items if k != 'filter']
|
|
932
933
|
d = dict(items2)
|
|
933
934
|
if filters:
|
|
934
|
-
d['filter'] = ','.join(filters)
|
|
935
|
+
d['filter'] = ','.join(filters) # ty:ignore[invalid-assignment]
|
|
935
936
|
|
|
936
937
|
job = JobBase.unserialize(d)
|
|
937
938
|
print(f'Adding {job}.')
|
|
@@ -984,15 +985,14 @@ class UrlwatchCommand:
|
|
|
984
985
|
print('You need to set up your bot token first (see documentation).')
|
|
985
986
|
self._exit(1)
|
|
986
987
|
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
self._exit(1)
|
|
988
|
+
with httpx.Client(http2=h2 is not None) if httpx else requests.Session() as http_client:
|
|
989
|
+
info = http_client.get(f'https://api.telegram.org/bot{bot_token}/getMe', timeout=60).json()
|
|
990
|
+
if not info['ok']:
|
|
991
|
+
print(f'Error with token {bot_token}: {info["description"]}.')
|
|
992
|
+
self._exit(1)
|
|
993
993
|
|
|
994
|
-
|
|
995
|
-
|
|
994
|
+
chats = {}
|
|
995
|
+
updates = http_client.get(f'https://api.telegram.org/bot{bot_token}/getUpdates', timeout=60).json()
|
|
996
996
|
if 'result' in updates:
|
|
997
997
|
for chat_info in updates['result']:
|
|
998
998
|
chat = chat_info['message']['chat']
|
|
@@ -1068,7 +1068,7 @@ class UrlwatchCommand:
|
|
|
1068
1068
|
)
|
|
1069
1069
|
return 1
|
|
1070
1070
|
|
|
1071
|
-
cfg: _ConfigReportersList = self.urlwatcher.config_storage.config['report'][reporter_name]
|
|
1071
|
+
cfg: _ConfigReportersList = self.urlwatcher.config_storage.config['report'][reporter_name] # ty:ignore[invalid-key]
|
|
1072
1072
|
if job_state: # we want a full report
|
|
1073
1073
|
cfg['enabled'] = True
|
|
1074
1074
|
self.urlwatcher.config_storage.config['display'][label] = True
|
|
@@ -1301,19 +1301,16 @@ class UrlwatchCommand:
|
|
|
1301
1301
|
self.urlwatcher.ssdb_storage.gc(
|
|
1302
1302
|
[job.guid for job in self.urlwatcher.jobs], self.urlwatch_config.gc_database
|
|
1303
1303
|
)
|
|
1304
|
-
self.urlwatcher.ssdb_storage.close()
|
|
1305
1304
|
self._exit(0)
|
|
1306
1305
|
|
|
1307
1306
|
if self.urlwatch_config.clean_database:
|
|
1308
1307
|
self.urlwatcher.ssdb_storage.clean_ssdb(
|
|
1309
1308
|
[job.guid for job in self.urlwatcher.jobs], self.urlwatch_config.clean_database
|
|
1310
1309
|
)
|
|
1311
|
-
self.urlwatcher.ssdb_storage.close()
|
|
1312
1310
|
self._exit(0)
|
|
1313
1311
|
|
|
1314
1312
|
if self.urlwatch_config.rollback_database:
|
|
1315
1313
|
exit_arg = self.rollback_database(self.urlwatch_config.rollback_database)
|
|
1316
|
-
self.urlwatcher.ssdb_storage.close()
|
|
1317
1314
|
self._exit(exit_arg)
|
|
1318
1315
|
|
|
1319
1316
|
if self.urlwatch_config.delete_snapshot:
|
|
@@ -11,7 +11,6 @@ import textwrap
|
|
|
11
11
|
# import os
|
|
12
12
|
from dataclasses import dataclass, field
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Collection
|
|
15
14
|
|
|
16
15
|
from webchanges import __doc__ as doc
|
|
17
16
|
from webchanges import __docs_url__, __project_name__, __version__
|
|
@@ -52,7 +51,7 @@ class CommandConfig(BaseConfig):
|
|
|
52
51
|
hooks_files: list[Path]
|
|
53
52
|
hooks_files_inputted: bool
|
|
54
53
|
install_chrome: bool
|
|
55
|
-
joblist:
|
|
54
|
+
joblist: list[str | int]
|
|
56
55
|
jobs_files: list[Path]
|
|
57
56
|
list_jobs: bool | str | None
|
|
58
57
|
log_file: Path
|