Skip to content

Commit 454992b

Browse files
committed
Version 3.34.2rc0
1 parent a30f88b commit 454992b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+242
-181
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,11 @@ repos:
152152
name: check Python static typing (ty)
153153
entry: ty
154154
args: ['check']
155-
language: python
156-
pass_filenames: true
155+
language: system
156+
pass_filenames: false
157157
types_or: [python, pyi, jupyter]
158-
exclude: storage_minidb.py
159158
require_serial: true
160-
additional_dependencies: [ty]
159+
# additional_dependencies: [ty]
161160
- id: cli-help
162161
name: update cli_help.txt (used in documentation build)
163162
entry: webchanges

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ can check out the `wish list <https://github.com/mborsetti/webchanges/blob/main/
3535
Internals, for changes that don't affect users. [triggers a minor patch]
3636
3737
38+
Version 3.34.2rc0
39+
-------------------
40+
2026-03-21
41+
42+
Fixed
43+
`````
44+
* Regression: Missing files in PyPi installation.
45+
46+
3847
Version 3.34.1
3948
-------------------
4049
2026-03-13

docs/inheritance_ascii_tree.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
def patch_subclasses(klass: type) -> None:
1919
"""Recursively patch webchanges classes to behave like standard python classes."""
20-
klass.__subclasses__ = type.__subclasses__.__get__(klass) # type: ignore[method-assign]
20+
klass.__subclasses__ = type.__subclasses__.__get__(klass) # ty:ignore[invalid-assignment]
2121

2222
for kls in klass.__subclasses__():
2323
patch_subclasses(kls)
@@ -28,7 +28,7 @@ def build_tree(klass: type, level: int) -> Iterator[str]:
2828
for i, kls in enumerate(klass.__subclasses__()):
2929
branch = '└───' if i + 1 == len(klass.__subclasses__()) else '├───'
3030
indent = '│ ' * (level - 1)
31-
yield ('' if level == 0 else indent + branch) + kls.__kind__ # type: ignore[attr-defined]
31+
yield ('' if level == 0 else indent + branch) + kls.__kind__ # ty:ignore[unresolved-attribute]
3232

3333
yield from build_tree(kls, level + 1)
3434

pyproject.toml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,14 @@ all = [
101101

102102
# Explicit package listing is required for building in tox -e new-install
103103
# https://setuptools.pypa.io/en/latest/userguide/package_discovery.html
104-
packages = ['webchanges', 'webchanges._vendored']
104+
packages = [
105+
'webchanges',
106+
'webchanges._vendored',
107+
'webchanges.filters',
108+
'webchanges.jobs',
109+
'webchanges.reporters',
110+
'webchanges.storage'
111+
]
105112

106113
[tool.setuptools.dynamic]
107114
version = { attr = 'webchanges.__version__' }
@@ -353,4 +360,13 @@ docstring-code-line-length = 'dynamic'
353360
# Config file documentation at https://docs.astral.sh/ty/reference/configuration/
354361

355362
[tool.ty.environment]
356-
extra-paths = ['webchanges', 'webchanges/storage/_sqlite3.py']
363+
extra-paths = ['webchanges']
364+
365+
[tool.ty.src]
366+
exclude = ["./webchanges/.**", "./webchanges/stora_minidb.py"]
367+
368+
[[tool.ty.overrides]]
369+
include = ["./webchanges/storage/_minidb.py"]
370+
371+
[tool.ty.overrides.rules]
372+
all = "ignore"

tests/data/hooks_example.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,14 @@ class CustomTextFileReporter(TextReporter):
8585

8686
__kind__ = 'custom_file'
8787

88-
def submit(self, **kwargs: Any) -> None: # type: ignore[override]
89-
Path(self.config['filename']).write_text('\n'.join(super().submit())) # ty:ignore[invalid-key, invalid-argument-type]
88+
def submit(self, **kwargs: Any) -> None: # ty:ignore[invalid-method-override]
89+
Path(self.config['filename']).write_text('\n'.join(super().submit())) # ty:ignore[invalid-key]
9090

9191

9292
class CustomHtmlFileReporter(HtmlReporter):
9393
"""Custom reporter that writes the HTML report to a file."""
9494

9595
__kind__ = 'custom_html'
9696

97-
def submit(self, **kwargs: Any) -> None: # type: ignore[override]
98-
Path(self.config['filename']).write_text('\n'.join(super().submit())) # ty:ignore[invalid-key, invalid-argument-type]
97+
def submit(self, **kwargs: Any) -> None: # ty:ignore[invalid-method-override]
98+
Path(self.config['filename']).write_text('\n'.join(super().submit())) # ty:ignore[invalid-key]

tests/test_command.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def new_command_config(jobs_file: Path = jobs_file, hooks_file: Path = hooks_fil
7070
config_file=config_file,
7171
jobs_def_file=jobs_file,
7272
hooks_def_file=hooks_file,
73-
ssdb_file=ssdb_file, # type: ignore[arg-type]
73+
ssdb_file=ssdb_file, # ty:ignore[invalid-argument-type]
7474
)
7575

7676

@@ -85,10 +85,10 @@ def urlwatch_command() -> Generator[UrlwatchCommand, None, None]:
8585
config_file=config_file,
8686
jobs_def_file=jobs_file,
8787
hooks_def_file=hooks_file,
88-
ssdb_file=':memory:', # type: ignore[arg-type]
88+
ssdb_file=':memory:', # ty:ignore[invalid-argument-type]
8989
),
9090
config_storage=config_storage,
91-
ssdb_storage=SsdbSQLite3Storage(':memory:'), # type: ignore[arg-type]
91+
ssdb_storage=SsdbSQLite3Storage(':memory:'), # ty:ignore[invalid-argument-type]
9292
jobs_storage=YamlJobsStorage([jobs_file]),
9393
) # main.py
9494
yield UrlwatchCommand(urlwatcher)
@@ -102,7 +102,7 @@ def urlwatch_command() -> Generator[UrlwatchCommand, None, None]:
102102
command_config = new_command_config(jobs_file=jobs_file)
103103
config_storage = YamlConfigStorage(config_file)
104104
config_storage.load()
105-
snapshot_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
105+
snapshot_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
106106
jobs_storage = YamlJobsStorage([jobs_file])
107107
urlwatcher = Urlwatch(command_config, config_storage, snapshot_storage, jobs_storage) # main.py
108108
urlwatch_command_common = UrlwatchCommand(urlwatcher)
@@ -164,7 +164,7 @@ def test_migration() -> None:
164164
config_file,
165165
jobs_file,
166166
hooks_file,
167-
ssdb_file, # type: ignore[arg-type]
167+
ssdb_file, # ty:ignore[invalid-argument-type]
168168
)
169169

170170

@@ -178,7 +178,7 @@ def test_first_run(capsys: pytest.CaptureFixture[str], tmp_path: Path) -> None:
178178
config_file2,
179179
jobs_file2,
180180
hooks_file,
181-
ssdb_file, # type: ignore[arg-type]
181+
ssdb_file, # ty:ignore[invalid-argument-type]
182182
)
183183
command_config2.edit = False
184184
first_run(command_config2)
@@ -192,7 +192,7 @@ def test_load_hooks_file_warning(recwarn: pytest.WarningsRecorder) -> None:
192192
hooks_file2 = tmp_path.joinpath('hooks_does_not_exist.py')
193193
load_hooks(hooks_file2, is_default=False)
194194
assert len(recwarn) == 1
195-
message = recwarn.pop(RuntimeWarning).message.args[0] # type: ignore[union-attr]
195+
message = recwarn.pop(RuntimeWarning).message.args[0] # ty:ignore[unresolved-attribute]
196196
assert message == f'Hooks file {hooks_file2} not imported because it does not exist or is not a file'
197197

198198

@@ -763,7 +763,7 @@ def test_modify_urls_move_location(
763763
# run jobs to save
764764
urlwatcher2.run_jobs()
765765
if hasattr(ssdb_storage2, '_copy_temp_to_permanent'):
766-
ssdb_storage2._copy_temp_to_permanent(delete=True) # type: ignore[attr-defined]
766+
ssdb_storage2._copy_temp_to_permanent(delete=True) # ty:ignore[call-non-callable]
767767

768768
# try changing job database location
769769
command_config2.change_location = old_loc, new_loc
@@ -915,7 +915,7 @@ def test_gc_database(capsys: pytest.CaptureFixture[str], monkeypatch: pytest.Mon
915915
def test_clean_database(capsys: pytest.CaptureFixture[str]) -> None:
916916
"""Test --clean-database [RETAIN_LIMIT]."""
917917
command_config.clean_database = True
918-
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
918+
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
919919
with pytest.raises(SystemExit) as pytest_wrapped_se:
920920
urlwatch_command_common.handle_actions()
921921
command_config.clean_database = None
@@ -924,7 +924,7 @@ def test_clean_database(capsys: pytest.CaptureFixture[str]) -> None:
924924
assert message == ''
925925

926926
# set up storage for testing
927-
database_engine = SsdbSQLite3Storage(':memory:') # type: ignore[arg-type]
927+
database_engine = SsdbSQLite3Storage(':memory:') # ty:ignore[invalid-argument-type]
928928
urlwatcher2, ssdb_storage2, command_config2 = prepare_storage_test(database_engine)
929929
urlwatch_command2 = UrlwatchCommand(urlwatcher2)
930930

@@ -933,13 +933,13 @@ def test_clean_database(capsys: pytest.CaptureFixture[str]) -> None:
933933
time.sleep(0.0001)
934934
urlwatch_command2.urlwatcher.run_jobs()
935935
if hasattr(ssdb_storage2, '_copy_temp_to_permanent'):
936-
ssdb_storage2._copy_temp_to_permanent(delete=True) # type: ignore[attr-defined]
936+
ssdb_storage2._copy_temp_to_permanent(delete=True) # ty:ignore[call-non-callable]
937937

938938
# clean database with RETAIN_LIMIT=2
939939
urlwatch_command2.urlwatch_config.clean_database = 2
940940
urlwatcher2.ssdb_storage.clean_ssdb(
941941
[job.guid for job in urlwatcher2.jobs],
942-
command_config2.clean_database, # type: ignore[arg-type]
942+
command_config2.clean_database, # ty:ignore[invalid-argument-type]
943943
)
944944
urlwatch_command2.urlwatch_config.clean_database = None
945945
guid = urlwatch_command2.urlwatcher.jobs[0].guid
@@ -949,7 +949,7 @@ def test_clean_database(capsys: pytest.CaptureFixture[str]) -> None:
949949
urlwatch_command2.urlwatch_config.clean_database = True
950950
urlwatcher2.ssdb_storage.clean_ssdb(
951951
[job.guid for job in urlwatcher2.jobs],
952-
command_config2.clean_database, # type: ignore[arg-type]
952+
command_config2.clean_database, # ty:ignore[invalid-argument-type]
953953
)
954954
urlwatch_command2.urlwatch_config.clean_database = None
955955
guid = urlwatch_command2.urlwatcher.jobs[0].guid
@@ -960,7 +960,7 @@ def test_rollback_database(capsys: pytest.CaptureFixture[str], monkeypatch: pyte
960960
# monkeypatches the "input" function, so that it simulates the user entering "y" in the terminal:
961961
monkeypatch.setattr('builtins.input', lambda _: 'y')
962962

963-
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
963+
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
964964
command_config.rollback_database = '1'
965965
with pytest.raises(SystemExit) as pytest_wrapped_se:
966966
urlwatch_command_common.handle_actions()
@@ -969,7 +969,7 @@ def test_rollback_database(capsys: pytest.CaptureFixture[str], monkeypatch: pyte
969969
message = capsys.readouterr().out
970970
assert 'No snapshots found after' in message
971971

972-
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
972+
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
973973
command_config.rollback_database = '10am'
974974
with pytest.raises(SystemExit) as pytest_wrapped_se:
975975
urlwatch_command_common.handle_actions()
@@ -978,7 +978,7 @@ def test_rollback_database(capsys: pytest.CaptureFixture[str], monkeypatch: pyte
978978
message = capsys.readouterr().out
979979
assert 'No snapshots found after' in message
980980

981-
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
981+
urlwatcher.ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
982982
command_config.rollback_database = 'Thisisjunk'
983983
with pytest.raises(ValueError) as pytest_wrapped_ve:
984984
urlwatch_command_common.handle_actions()
@@ -1194,7 +1194,7 @@ def test_locate_storage_file() -> None:
11941194

11951195
def test_job_states_verb() -> None:
11961196
jobs_file = config_path.joinpath('jobs-time.yaml')
1197-
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
1197+
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
11981198
jobs_storage = YamlJobsStorage([jobs_file])
11991199
command_config = new_command_config(jobs_file=jobs_file)
12001200
urlwatcher = Urlwatch(command_config, config_storage, ssdb_storage, jobs_storage) # main.py
@@ -1213,7 +1213,7 @@ def test_job_states_verb() -> None:
12131213

12141214
def test_job_states_verb_notimestamp_unchanged() -> None:
12151215
jobs_file = config_path.joinpath('jobs-time.yaml')
1216-
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
1216+
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
12171217
jobs_storage = YamlJobsStorage([jobs_file])
12181218
command_config = new_command_config(jobs_file=jobs_file)
12191219
urlwatcher = Urlwatch(command_config, config_storage, ssdb_storage, jobs_storage) # main.py
@@ -1249,7 +1249,7 @@ def test_job_states_verb_notimestamp_unchanged() -> None:
12491249

12501250
def test_job_states_verb_notimestamp_changed() -> None:
12511251
jobs_file = config_path.joinpath('jobs-time.yaml')
1252-
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
1252+
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
12531253
jobs_storage = YamlJobsStorage([jobs_file])
12541254
command_config = new_command_config(jobs_file=jobs_file)
12551255
urlwatcher = Urlwatch(command_config, config_storage, ssdb_storage, jobs_storage) # main.py

tests/test_differs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def generate_random_string(length: int = 39) -> str:
112112
def job_state() -> Generator[JobState, None, None]:
113113
"""Get a JobState object for testing."""
114114
ssdb_file = ':memory:'
115-
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # type: ignore[arg-type]
115+
ssdb_storage = SsdbSQLite3Storage(ssdb_file) # ty:ignore[invalid-argument-type]
116116
job_state = JobState(ssdb_storage, ShellJob(command=''))
117117
job_state.old_timestamp = 1605147837.511478 # initial release of webchanges!
118118
job_state.new_timestamp = 1605147837.511478

tests/test_docs_filters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ def test_jobs(job: JobBase) -> None:
144144
expected_output_data = d['output']
145145

146146
# noinspection PyTypeChecker
147-
with JobState(None, job) as job_state: # type: ignore[arg-type]
148-
for filter_kind, subfilter in FilterBase.normalize_filter_list(job_state.job.filters):
147+
with JobState(None, job) as job_state: # ty:ignore[invalid-argument-type]
148+
for filter_kind, subfilter in FilterBase.normalize_filter_list(job_state.job.filters): # ty:ignore[invalid-argument-type]
149149
if (
150150
filter_kind == 'beautify' or (filter_kind == 'html2text' and subfilter.get('method') == 'bs4')
151151
) and not bs4_is_installed:

tests/test_docs_hooks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ def test_url(job: JobBase) -> None:
149149
d = testdata[job.url]
150150
data = d['input']
151151
# noinspection PyTypeChecker
152-
with JobState(None, job) as job_state: # type: ignore[arg-type]
152+
with JobState(None, job) as job_state: # ty:ignore[invalid-argument-type]
153153
data, _ = FilterBase.auto_process(job_state, data, '')
154-
for filter_kind, subfilter in FilterBase.normalize_filter_list(job_state.job.filters):
154+
for filter_kind, subfilter in FilterBase.normalize_filter_list(job_state.job.filters): # ty:ignore[invalid-argument-type]
155155
data, _ = FilterBase.process(filter_kind, subfilter, job_state, data, '')
156156

157157
expected_output_data = d['output']

0 commit comments

Comments
 (0)