check-empty 2.0.0__tar.gz → 3.0.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.
- {check_empty-2.0.0 → check_empty-3.0.0}/PKG-INFO +9 -8
- {check_empty-2.0.0 → check_empty-3.0.0}/README.md +7 -6
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/__init__.py +36 -42
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/archives.py +10 -10
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/reporter/__init__.py +11 -9
- check_empty-2.0.0/check_empty/reporter/abc.py → check_empty-3.0.0/check_empty/reporter/abcdef.py +8 -6
- check_empty-2.0.0/check_empty/reporter/dict.py → check_empty-3.0.0/check_empty/reporter/dct.py +4 -5
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/reporter/exceptions.py +14 -10
- {check_empty-2.0.0 → check_empty-3.0.0}/pyproject.toml +12 -16
- {check_empty-2.0.0 → check_empty-3.0.0}/pyproject.toml.orig +12 -11
- {check_empty-2.0.0 → check_empty-3.0.0}/AUTHORS.md +0 -0
- {check_empty-2.0.0 → check_empty-3.0.0}/LICENSE +0 -0
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/__main__.py +3 -3
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/constants.py +3 -3
- {check_empty-2.0.0 → check_empty-3.0.0}/check_empty/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: check-empty
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Command-line utility, as well as a hook usable by the Python pre-commit framework, and a GitHub Action, to ensure that selected files are empty.
|
|
5
5
|
Keywords: check,command-line,empty,files,github-action,helper,hook,lightweight,pre-commit,prek,tool,utility
|
|
6
6
|
Author: Jonathan Dung
|
|
@@ -27,7 +27,7 @@ Classifier: Topic :: Utilities
|
|
|
27
27
|
Classifier: Typing :: Typed
|
|
28
28
|
Requires-Dist: py7zr==1.1.3 ; extra == '7z'
|
|
29
29
|
Requires-Dist: acefile==0.6.14 ; extra == 'ace'
|
|
30
|
-
Requires-Dist: check-empty[7z,ace,ar,lzh,rar]==
|
|
30
|
+
Requires-Dist: check-empty[7z,ace,ar,lzh,rar]==3.0.0 ; extra == 'all'
|
|
31
31
|
Requires-Dist: arpy==2.4.0 ; extra == 'ar'
|
|
32
32
|
Requires-Dist: lhafile==0.3.1 ; extra == 'lzh'
|
|
33
33
|
Requires-Dist: rarfile==4.5 ; extra == 'rar'
|
|
@@ -42,7 +42,7 @@ Provides-Extra: lzh
|
|
|
42
42
|
Provides-Extra: rar
|
|
43
43
|
Description-Content-Type: text/markdown
|
|
44
44
|
|
|
45
|
-
# [check-empty](https://pypi.org/p/check-empty)
|
|
45
|
+
# [check-empty](https://pypi.org/p/check-empty/3.0.0)
|
|
46
46
|
|
|
47
47
|
[](https://github.com/TheBSD/StandWithPalestine/blob/main/docs/README.md)
|
|
48
48
|
|
|
@@ -57,7 +57,8 @@ specified.
|
|
|
57
57
|
|
|
58
58
|
## Prerequisites
|
|
59
59
|
|
|
60
|
-
Supports every Python 3.10 runtime. There are no other requirements
|
|
60
|
+
Supports every Python 3.10 runtime. There are no other requirements unless you want to
|
|
61
|
+
check if files in certain types of (compressed) archives are empty.
|
|
61
62
|
|
|
62
63
|
## Quickstart
|
|
63
64
|
|
|
@@ -125,7 +126,7 @@ As a pre-commit hook:
|
|
|
125
126
|
# .pre-commit-config.yaml
|
|
126
127
|
repos:
|
|
127
128
|
- repo: https://github.com/jonathandung/check-empty
|
|
128
|
-
rev:
|
|
129
|
+
rev: v3.0.0 # repository version
|
|
129
130
|
hooks:
|
|
130
131
|
- id: check-empty # the hook
|
|
131
132
|
args: # example list of arguments
|
|
@@ -141,7 +142,7 @@ equivalent in `prek.toml` format:
|
|
|
141
142
|
```toml
|
|
142
143
|
[[repos]]
|
|
143
144
|
repo = "https://github.com/jonathandung/check-empty"
|
|
144
|
-
rev = "
|
|
145
|
+
rev = "v3.0.0"
|
|
145
146
|
|
|
146
147
|
[[repos.hooks]]
|
|
147
148
|
id = "check-empty"
|
|
@@ -165,7 +166,7 @@ or (TOML 1.1+):
|
|
|
165
166
|
# using multiline inline tables
|
|
166
167
|
[[repos]]
|
|
167
168
|
repo = "https://github.com/jonathandung/check-empty"
|
|
168
|
-
rev = "
|
|
169
|
+
rev = "v3.0.0"
|
|
169
170
|
hooks = [{
|
|
170
171
|
id = "check-empty",
|
|
171
172
|
args = ["-Q"],
|
|
@@ -185,7 +186,7 @@ As a GitHub Actions workflow step:
|
|
|
185
186
|
|
|
186
187
|
```yaml
|
|
187
188
|
steps:
|
|
188
|
-
- uses: jonathandung/check-empty@
|
|
189
|
+
- uses: jonathandung/check-empty@v3.0.0 # the latest version on the GitHub Actions
|
|
189
190
|
# marketplace; this step will fail and subsequent jobs will not run if any file is
|
|
190
191
|
# not empty
|
|
191
192
|
with:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# [check-empty](https://pypi.org/p/check-empty)
|
|
1
|
+
# [check-empty](https://pypi.org/p/check-empty/3.0.0)
|
|
2
2
|
|
|
3
3
|
[](https://github.com/TheBSD/StandWithPalestine/blob/main/docs/README.md)
|
|
4
4
|
|
|
@@ -13,7 +13,8 @@ specified.
|
|
|
13
13
|
|
|
14
14
|
## Prerequisites
|
|
15
15
|
|
|
16
|
-
Supports every Python 3.10 runtime. There are no other requirements
|
|
16
|
+
Supports every Python 3.10 runtime. There are no other requirements unless you want to
|
|
17
|
+
check if files in certain types of (compressed) archives are empty.
|
|
17
18
|
|
|
18
19
|
## Quickstart
|
|
19
20
|
|
|
@@ -81,7 +82,7 @@ As a pre-commit hook:
|
|
|
81
82
|
# .pre-commit-config.yaml
|
|
82
83
|
repos:
|
|
83
84
|
- repo: https://github.com/jonathandung/check-empty
|
|
84
|
-
rev:
|
|
85
|
+
rev: v3.0.0 # repository version
|
|
85
86
|
hooks:
|
|
86
87
|
- id: check-empty # the hook
|
|
87
88
|
args: # example list of arguments
|
|
@@ -97,7 +98,7 @@ equivalent in `prek.toml` format:
|
|
|
97
98
|
```toml
|
|
98
99
|
[[repos]]
|
|
99
100
|
repo = "https://github.com/jonathandung/check-empty"
|
|
100
|
-
rev = "
|
|
101
|
+
rev = "v3.0.0"
|
|
101
102
|
|
|
102
103
|
[[repos.hooks]]
|
|
103
104
|
id = "check-empty"
|
|
@@ -121,7 +122,7 @@ or (TOML 1.1+):
|
|
|
121
122
|
# using multiline inline tables
|
|
122
123
|
[[repos]]
|
|
123
124
|
repo = "https://github.com/jonathandung/check-empty"
|
|
124
|
-
rev = "
|
|
125
|
+
rev = "v3.0.0"
|
|
125
126
|
hooks = [{
|
|
126
127
|
id = "check-empty",
|
|
127
128
|
args = ["-Q"],
|
|
@@ -141,7 +142,7 @@ As a GitHub Actions workflow step:
|
|
|
141
142
|
|
|
142
143
|
```yaml
|
|
143
144
|
steps:
|
|
144
|
-
- uses: jonathandung/check-empty@
|
|
145
|
+
- uses: jonathandung/check-empty@v3.0.0 # the latest version on the GitHub Actions
|
|
145
146
|
# marketplace; this step will fail and subsequent jobs will not run if any file is
|
|
146
147
|
# not empty
|
|
147
148
|
with:
|
|
@@ -7,26 +7,24 @@ Pre-commit hook, command-line tool and GitHub Action all-in-one.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import os
|
|
11
10
|
from contextlib import suppress
|
|
12
11
|
|
|
13
|
-
from
|
|
12
|
+
from check_empty import constants, reporter
|
|
14
13
|
|
|
14
|
+
__all__ = ('Handler', 'check', 'default_reporter')
|
|
15
|
+
__version__ = '3.0.0'
|
|
16
|
+
"""The version of the package."""
|
|
17
|
+
default_reporter: reporter.Reporter = reporter.Reporter()
|
|
18
|
+
"""The default reporter used by :func:`check`."""
|
|
15
19
|
TYPE_CHECKING = False
|
|
16
20
|
if TYPE_CHECKING:
|
|
17
21
|
from collections.abc import Callable, Iterable
|
|
18
|
-
from types import
|
|
22
|
+
from types import TracebackType
|
|
19
23
|
from typing import Any, SupportsIndex
|
|
20
24
|
|
|
21
25
|
from _typeshed import FileDescriptorOrPath
|
|
22
26
|
from typing_extensions import Self
|
|
23
27
|
|
|
24
|
-
__all__ = ('Handler', 'check', 'default_reporter')
|
|
25
|
-
__version__ = '2.0.0'
|
|
26
|
-
"""The version of the package."""
|
|
27
|
-
default_reporter: reporter.Reporter = reporter.Reporter()
|
|
28
|
-
"""The default reporter used by :func:`check`."""
|
|
29
|
-
|
|
30
28
|
|
|
31
29
|
class Handler:
|
|
32
30
|
"""Used to handle errors when opening a file."""
|
|
@@ -36,22 +34,18 @@ class Handler:
|
|
|
36
34
|
"""The file descriptor or string path to the file being handled."""
|
|
37
35
|
c: bool
|
|
38
36
|
"""Whether an I/O error was handled."""
|
|
39
|
-
f: Callable[[
|
|
40
|
-
"""The function to call
|
|
41
|
-
|
|
42
|
-
Should take a string representing the error message as the only argument and
|
|
43
|
-
preferably return ``None``.
|
|
44
|
-
"""
|
|
45
|
-
j: Callable[[str], None]
|
|
37
|
+
f: Callable[[OSError], object]
|
|
38
|
+
"""The function to call on the I/O error being handled."""
|
|
39
|
+
j: Callable[[str], object]
|
|
46
40
|
"""The function to call when handling the case where the file is missing.
|
|
47
41
|
|
|
48
42
|
Should take the path to the file or a string encapsulating the validity of the file
|
|
49
|
-
descriptor as the only argument
|
|
43
|
+
descriptor as the only argument.
|
|
50
44
|
"""
|
|
51
45
|
v: str | None
|
|
52
46
|
"""The cached value of :attr:`e`."""
|
|
53
47
|
|
|
54
|
-
def __init__(self, *a: Any)
|
|
48
|
+
def __init__(self, *a: Any): # ruff: ignore[any-type]
|
|
55
49
|
"""Initialize the handler."""
|
|
56
50
|
self.j, self.f, self.a = a
|
|
57
51
|
self.v = None
|
|
@@ -71,7 +65,7 @@ class Handler:
|
|
|
71
65
|
...
|
|
72
66
|
|
|
73
67
|
@property
|
|
74
|
-
def e(self, s: str = 'invalid fd (negative): %d', t: str = 'fd: %d') -> str:
|
|
68
|
+
def e(self, s: str = 'invalid fd (negative): %d', t: str = 'fd: %d') -> str:
|
|
75
69
|
"""The file path itself, or the file descriptor coerced to a string."""
|
|
76
70
|
r = self.v
|
|
77
71
|
if r is None:
|
|
@@ -92,7 +86,7 @@ class Handler:
|
|
|
92
86
|
"""
|
|
93
87
|
if t is None or not isinstance(v, OSError):
|
|
94
88
|
return False
|
|
95
|
-
self.j(self.e) if v.errno == constants.ENOENT else self.f(
|
|
89
|
+
self.j(self.e) if v.errno == constants.ENOENT else self.f(v)
|
|
96
90
|
self.c = True
|
|
97
91
|
return True
|
|
98
92
|
|
|
@@ -104,7 +98,7 @@ def check(
|
|
|
104
98
|
may_not_exist: bool = False,
|
|
105
99
|
verbosity: SupportsIndex = 2,
|
|
106
100
|
recurse_into: SupportsIndex = constants.RecurseInto.NONE,
|
|
107
|
-
reporter: reporter.
|
|
101
|
+
reporter: reporter.abcdef.ReporterABC = default_reporter,
|
|
108
102
|
) -> int:
|
|
109
103
|
# ruff: ignore[docstring-missing-exception]
|
|
110
104
|
r"""Check the emptiness of files, recursing into directories if passed.
|
|
@@ -130,13 +124,14 @@ def check(
|
|
|
130
124
|
The integer exit code calculated by the reporter.
|
|
131
125
|
|
|
132
126
|
"""
|
|
127
|
+
from os import fsdecode, scandir, stat
|
|
128
|
+
|
|
133
129
|
files = list(files)
|
|
134
130
|
if not files:
|
|
135
131
|
return 0
|
|
136
132
|
k, j, t, n, o = [0] * 5, [], 0, len(files), files.pop
|
|
137
133
|
u, e, _ = j.extend, j.pop, lambda v: lambda _, k=k: k.__setitem__(v, k[v] + 1)
|
|
138
134
|
verbosity, recurse_into = (type(x).__index__(x) for x in (verbosity, recurse_into))
|
|
139
|
-
# ruff: disable[magic-value-comparison]
|
|
140
135
|
if verbosity > 4:
|
|
141
136
|
b = ['']
|
|
142
137
|
f = b.append
|
|
@@ -149,7 +144,7 @@ def check(
|
|
|
149
144
|
v = ra = None
|
|
150
145
|
x = aa = lambda _: None
|
|
151
146
|
if verbosity > 2:
|
|
152
|
-
z, w = [''], [
|
|
147
|
+
z, w = [''], []
|
|
153
148
|
i = z.append, w.append
|
|
154
149
|
else:
|
|
155
150
|
z = w = None
|
|
@@ -159,11 +154,10 @@ def check(
|
|
|
159
154
|
g = r.append
|
|
160
155
|
else:
|
|
161
156
|
r, g = None, _(3)
|
|
162
|
-
# ruff: enable[magic-value-comparison]
|
|
163
157
|
zp, tr, rr, z7, ar, lh, ac = map(recurse_into.__and__, constants.ARCHIVE_FORMATS)
|
|
164
158
|
an = bool(recurse_into)
|
|
165
159
|
if an:
|
|
166
|
-
from
|
|
160
|
+
from check_empty import archives as av
|
|
167
161
|
md = 'a' if clear else 'r'
|
|
168
162
|
if TYPE_CHECKING:
|
|
169
163
|
import tarfile as tr
|
|
@@ -208,20 +202,19 @@ def check(
|
|
|
208
202
|
else:
|
|
209
203
|
f(a)
|
|
210
204
|
|
|
211
|
-
def v(
|
|
205
|
+
def v(f: Callable[[str], Any], e: type[BaseException]) -> bool:
|
|
212
206
|
nonlocal d
|
|
213
|
-
with suppress(
|
|
214
|
-
d =
|
|
207
|
+
with suppress(e):
|
|
208
|
+
d = f(a)
|
|
215
209
|
return True
|
|
216
210
|
return False
|
|
217
211
|
|
|
218
|
-
if tr and v(tr,
|
|
212
|
+
if tr and v(tr.open, tr.TarError):
|
|
219
213
|
aa(a)
|
|
220
214
|
for r in d.getmembers():
|
|
221
215
|
a, s = q = r.name, r.size
|
|
222
216
|
e()
|
|
223
|
-
if clear
|
|
224
|
-
av.purge_tar(d)
|
|
217
|
+
av.purge_tar(d) if clear else d.close()
|
|
225
218
|
elif zp and zp.is_zipfile(a):
|
|
226
219
|
with zp.ZipFile(a, md) as d:
|
|
227
220
|
aa(a)
|
|
@@ -248,14 +241,14 @@ def check(
|
|
|
248
241
|
for r in d.infolist():
|
|
249
242
|
a, s = q = r.filename, r.file_size
|
|
250
243
|
w()
|
|
251
|
-
elif ar and v(ar,
|
|
244
|
+
elif ar and v(ar.Archive, ar.ArchiveFormatError):
|
|
252
245
|
aa(a)
|
|
253
246
|
for r in d.infolist():
|
|
254
247
|
a, s = q = r.name, r.size
|
|
255
248
|
e()
|
|
256
249
|
if clear:
|
|
257
250
|
av.purge_ar(d, ar.HEADER_GNU)
|
|
258
|
-
elif ac and v(ac,
|
|
251
|
+
elif ac and v(ac.open, ac.AceError):
|
|
259
252
|
aa(a)
|
|
260
253
|
for r in filter(ac.AceMember.is_reg, d):
|
|
261
254
|
a, s = q = r.filename, r.size
|
|
@@ -278,24 +271,25 @@ def check(
|
|
|
278
271
|
try:
|
|
279
272
|
return an and ha(a)
|
|
280
273
|
except Exception as e: # ruff: ignore[blind-except]
|
|
281
|
-
i[1](
|
|
274
|
+
i[1](e)
|
|
282
275
|
return True
|
|
283
276
|
|
|
284
277
|
while files:
|
|
285
278
|
a, q = o(), None
|
|
286
279
|
m = isinstance(a, int)
|
|
287
280
|
if not m:
|
|
288
|
-
a =
|
|
281
|
+
a = fsdecode(a)
|
|
289
282
|
with Handler(*i, a) as h:
|
|
290
|
-
q =
|
|
283
|
+
q = stat(a) # ruff: ignore[os-stat]
|
|
291
284
|
if q is None:
|
|
292
285
|
continue
|
|
293
286
|
c = h.e
|
|
294
287
|
if q.st_mode & constants.TYPE_MASK == constants.S_IFDIR:
|
|
295
288
|
if m:
|
|
296
289
|
raise constants.DIRFD_UNSUPPORTED
|
|
297
|
-
|
|
298
|
-
|
|
290
|
+
with h:
|
|
291
|
+
u(scandir(c))
|
|
292
|
+
x(c)
|
|
299
293
|
continue
|
|
300
294
|
if isinstance(a, str) and hb(a):
|
|
301
295
|
continue
|
|
@@ -312,8 +306,9 @@ def check(
|
|
|
312
306
|
m = e()
|
|
313
307
|
a = m.path
|
|
314
308
|
if m.is_dir():
|
|
315
|
-
|
|
316
|
-
|
|
309
|
+
with Handler(*i, a):
|
|
310
|
+
u(scandir(a))
|
|
311
|
+
x(a)
|
|
317
312
|
continue
|
|
318
313
|
if hb(a):
|
|
319
314
|
continue
|
|
@@ -326,8 +321,7 @@ def check(
|
|
|
326
321
|
t += s
|
|
327
322
|
if clear:
|
|
328
323
|
Handler(*i, a).o()
|
|
329
|
-
|
|
330
|
-
x, d = k[1] if z is None else len(z) - 1, k[2] if w is None else len(w) - 1
|
|
324
|
+
x, d = k[1] if z is None else len(z) - 1, k[2] if w is None else len(w)
|
|
331
325
|
y, p = k[3] if r is None else len(r), k[0] if b is None else len(b) - 1
|
|
332
326
|
reporter.report(z, w, v, b, r, x, y, d, p, n, t, verbosity, clear)
|
|
333
327
|
reporter.reset_out()
|
|
@@ -7,15 +7,6 @@ from itertools import filterfalse
|
|
|
7
7
|
from operator import attrgetter
|
|
8
8
|
from tempfile import NamedTemporaryFile
|
|
9
9
|
|
|
10
|
-
TYPE_CHECKING = False
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
import tarfile
|
|
13
|
-
import zipfile
|
|
14
|
-
from collections.abc import Callable, Iterable
|
|
15
|
-
from typing import Final, Literal
|
|
16
|
-
|
|
17
|
-
import arpy
|
|
18
|
-
import py7zr
|
|
19
10
|
__all__ = (
|
|
20
11
|
'AR_FS',
|
|
21
12
|
'AR_MAG',
|
|
@@ -34,6 +25,15 @@ AR_SKIP: Final[
|
|
|
34
25
|
Literal[b'/', b'//', b'/SYM64/', b'__.SYMDEF', b'__.SYMDEF SORTED'] | None
|
|
35
26
|
]
|
|
36
27
|
] = frozenset((b'/', b'//', b'/SYM64/', b'__.SYMDEF', b'__.SYMDEF SORTED', None))
|
|
28
|
+
TYPE_CHECKING = False
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
import tarfile
|
|
31
|
+
import zipfile
|
|
32
|
+
from collections.abc import Callable, Iterable
|
|
33
|
+
from typing import Final, Literal
|
|
34
|
+
|
|
35
|
+
import py7zr
|
|
36
|
+
from arpy import Archive
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def clear_file_in_zip(z: zipfile.ZipFile, i: zipfile.ZipInfo) -> None:
|
|
@@ -71,7 +71,7 @@ def purge_tar(t: tarfile.TarFile) -> None:
|
|
|
71
71
|
os.replace(p.name, x)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
def purge_ar(a:
|
|
74
|
+
def purge_ar(a: Archive, g: int) -> None:
|
|
75
75
|
"""Clear the contents of each file in a .a, .ar or .lib archive."""
|
|
76
76
|
a.read_all_headers()
|
|
77
77
|
i, n = a.headers, a.file.name
|
|
@@ -5,19 +5,18 @@ from __future__ import annotations
|
|
|
5
5
|
import itertools as i
|
|
6
6
|
import sys as s
|
|
7
7
|
|
|
8
|
-
from . import
|
|
9
|
-
|
|
10
|
-
TYPE_CHECKING = False
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from typing import IO
|
|
8
|
+
from check_empty.reporter import abcdef, dct as dct
|
|
13
9
|
|
|
14
10
|
__all__ = ('DelayedReporter', 'Reporter')
|
|
11
|
+
TYPE_CHECKING = False
|
|
15
12
|
|
|
16
13
|
|
|
17
|
-
class Reporter(
|
|
14
|
+
class Reporter(abcdef.ReporterABC):
|
|
18
15
|
"""Concrete and default reporter implementation that prints output to a stream."""
|
|
19
16
|
|
|
20
17
|
if TYPE_CHECKING:
|
|
18
|
+
from typing import IO
|
|
19
|
+
|
|
21
20
|
o: IO[str] | None
|
|
22
21
|
|
|
23
22
|
def to(self, out: IO[str] | None = None) -> IO[str] | None:
|
|
@@ -35,7 +34,7 @@ class Reporter(abc.ReporterABC):
|
|
|
35
34
|
def report( # ruff: ignore[too-many-arguments, too-many-positional-arguments]
|
|
36
35
|
self,
|
|
37
36
|
z: list[str] | None,
|
|
38
|
-
w: list[
|
|
37
|
+
w: list[OSError] | None,
|
|
39
38
|
a: list[str] | None,
|
|
40
39
|
b: list[str] | None,
|
|
41
40
|
r: list[tuple[str, int]] | None,
|
|
@@ -68,7 +67,7 @@ class Reporter(abc.ReporterABC):
|
|
|
68
67
|
else '\nAll files were found'
|
|
69
68
|
)
|
|
70
69
|
if w is not None:
|
|
71
|
-
q('\nError: '.join(w))
|
|
70
|
+
q('\nError: '.join(i.chain(('',), map(str, w))))
|
|
72
71
|
if d:
|
|
73
72
|
q(f'\n{d} I/O error{"s" if d > 1 else ""} encountered')
|
|
74
73
|
if b is not None:
|
|
@@ -93,5 +92,8 @@ class Reporter(abc.ReporterABC):
|
|
|
93
92
|
q.close()
|
|
94
93
|
|
|
95
94
|
|
|
96
|
-
class DelayedReporter(
|
|
95
|
+
class DelayedReporter(abcdef.DelayedReporterMixin, Reporter):
|
|
97
96
|
"""The delayed version of the default reporter."""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
del TYPE_CHECKING
|
check_empty-2.0.0/check_empty/reporter/abc.py → check_empty-3.0.0/check_empty/reporter/abcdef.py
RENAMED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
"""Abstract base classes for reporters."""
|
|
1
|
+
"""Abstract base classes definitions ("abcdef") for reporters."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import abc as a
|
|
6
6
|
|
|
7
|
-
from .exceptions import NoReport
|
|
7
|
+
from check_empty.reporter.exceptions import NoReport
|
|
8
8
|
|
|
9
|
+
__all__ = ('DelayedReporterMixin', 'ReporterABC')
|
|
9
10
|
TYPE_CHECKING = False
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
|
-
__all__ = ('DelayedReporterMixin', 'ReporterABC')
|
|
14
|
-
|
|
15
14
|
|
|
16
15
|
class ReporterABC(metaclass=a.ABCMeta):
|
|
17
16
|
"""Abstract base class for all reporters accepted by :func:`~check_empty.check`."""
|
|
@@ -23,7 +22,7 @@ class ReporterABC(metaclass=a.ABCMeta):
|
|
|
23
22
|
def report( # ruff: ignore[too-many-arguments, too-many-positional-arguments]
|
|
24
23
|
self,
|
|
25
24
|
z: list[str] | None,
|
|
26
|
-
w: list[
|
|
25
|
+
w: list[OSError] | None,
|
|
27
26
|
a: list[str] | None,
|
|
28
27
|
b: list[str] | None,
|
|
29
28
|
r: list[tuple[str, int]] | None,
|
|
@@ -41,7 +40,7 @@ class ReporterABC(metaclass=a.ABCMeta):
|
|
|
41
40
|
|
|
42
41
|
Args:
|
|
43
42
|
z: list of paths to files that were not found.
|
|
44
|
-
w: list of
|
|
43
|
+
w: list of I/O errors when processing non-missing files.
|
|
45
44
|
a: list of directories that were recursed into.
|
|
46
45
|
b: list of empty file paths.
|
|
47
46
|
r: list of 2-tuples representing non-empty files and their sizes.
|
|
@@ -127,3 +126,6 @@ class DelayedReporterMixin(ReporterABC):
|
|
|
127
126
|
if a is None:
|
|
128
127
|
raise NoReport(self)
|
|
129
128
|
super().report(*a)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
del TYPE_CHECKING
|
check_empty-2.0.0/check_empty/reporter/dict.py → check_empty-3.0.0/check_empty/reporter/dct.py
RENAMED
|
@@ -4,16 +4,15 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import itertools as i
|
|
6
6
|
|
|
7
|
-
from . import exceptions as _
|
|
8
|
-
from .
|
|
7
|
+
from check_empty.reporter import exceptions as _
|
|
8
|
+
from check_empty.reporter.abcdef import ReporterABC
|
|
9
9
|
|
|
10
|
+
__all__ = ('DictReporter', 'SelfReporter')
|
|
10
11
|
TYPE_CHECKING = False
|
|
11
12
|
if TYPE_CHECKING:
|
|
12
13
|
from collections.abc import Iterable, MutableMapping
|
|
13
14
|
from typing import Any, Final
|
|
14
15
|
|
|
15
|
-
__all__ = ('DictReporter', 'SelfReporter')
|
|
16
|
-
|
|
17
16
|
|
|
18
17
|
class DictReporter(ReporterABC):
|
|
19
18
|
"""Dump the metrics into a dictionary-like object."""
|
|
@@ -63,7 +62,7 @@ class DictReporter(ReporterABC):
|
|
|
63
62
|
The previous output mapping, or ``None`` if no redirection is in effect.
|
|
64
63
|
"""
|
|
65
64
|
|
|
66
|
-
def __init__(self, keys: Iterable[str | None] | None = None)
|
|
65
|
+
def __init__(self, keys: Iterable[str | None] | None = None):
|
|
67
66
|
"""Initialize the reporter.
|
|
68
67
|
|
|
69
68
|
Args:
|
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
TYPE_CHECKING = False
|
|
6
|
-
if TYPE_CHECKING:
|
|
7
|
-
from typing import ClassVar
|
|
8
|
-
|
|
9
|
-
from .abc import DelayedReporterMixin, ReporterABC
|
|
10
|
-
from .dict import DictReporter
|
|
11
|
-
|
|
12
5
|
__all__ = (
|
|
13
6
|
'IncorrectKeynames',
|
|
14
7
|
'IncorrectKeynamesLength',
|
|
@@ -17,6 +10,12 @@ __all__ = (
|
|
|
17
10
|
'NoReport',
|
|
18
11
|
'ReporterError',
|
|
19
12
|
)
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import ClassVar
|
|
16
|
+
|
|
17
|
+
from check_empty.reporter.abcdef import DelayedReporterMixin, ReporterABC
|
|
18
|
+
from check_empty.reporter.dct import DictReporter
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
class ReporterError(Exception):
|
|
@@ -27,7 +26,7 @@ class ReporterError(Exception):
|
|
|
27
26
|
message: ClassVar[str]
|
|
28
27
|
"""The message of the exception."""
|
|
29
28
|
|
|
30
|
-
def __init__(self, reporter: ReporterABC)
|
|
29
|
+
def __init__(self, reporter: ReporterABC):
|
|
31
30
|
"""Initialize the exception.
|
|
32
31
|
|
|
33
32
|
Args:
|
|
@@ -46,7 +45,7 @@ class NoReport(ReporterError):
|
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
class IncorrectKeynames(ReporterError):
|
|
49
|
-
"""A :class:`check_empty.reporter.
|
|
48
|
+
"""A :class:`check_empty.reporter.dct.DictReporter` got invalid ``keys``."""
|
|
50
49
|
|
|
51
50
|
reporter: DictReporter
|
|
52
51
|
"""The reporter concerned."""
|
|
@@ -65,6 +64,11 @@ class IncorrectKeynamesType(IncorrectKeynames):
|
|
|
65
64
|
|
|
66
65
|
|
|
67
66
|
class NoOutputMapping(ReporterError):
|
|
68
|
-
"""A :class:`check_empty.reporter.
|
|
67
|
+
"""A :class:`check_empty.reporter.dct.DictReporter` had no output mapping."""
|
|
69
68
|
|
|
69
|
+
reporter: DictReporter
|
|
70
|
+
"""The reporter concerned."""
|
|
70
71
|
message = 'no mapping to output to'
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
del TYPE_CHECKING
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.12.
|
|
2
|
+
requires = ["uv_build>=0.12.19"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[dependency-groups]
|
|
@@ -55,7 +55,7 @@ license-files = [
|
|
|
55
55
|
name = "check-empty"
|
|
56
56
|
readme = "README.md"
|
|
57
57
|
requires-python = ">=3.10"
|
|
58
|
-
version = "
|
|
58
|
+
version = "3.0.0"
|
|
59
59
|
|
|
60
60
|
[[project.authors]]
|
|
61
61
|
name = "Jonathan Dung"
|
|
@@ -68,7 +68,7 @@ email = "jonathandung@yahoo.com"
|
|
|
68
68
|
[project.optional-dependencies]
|
|
69
69
|
7z = ["py7zr==1.1.3"]
|
|
70
70
|
ace = ["acefile==0.6.14"]
|
|
71
|
-
all = ["check-empty[7z,ace,ar,lzh,rar]==
|
|
71
|
+
all = ["check-empty[7z,ace,ar,lzh,rar]==3.0.0"]
|
|
72
72
|
ar = ["arpy==2.4.0"]
|
|
73
73
|
lzh = ["lhafile==0.3.1"]
|
|
74
74
|
rar = ["rarfile==4.5"]
|
|
@@ -77,7 +77,7 @@ rar = ["rarfile==4.5"]
|
|
|
77
77
|
check-empty = "check_empty.__main__:main"
|
|
78
78
|
|
|
79
79
|
[tool.ruff]
|
|
80
|
-
required-version = ">=0.16.
|
|
80
|
+
required-version = ">=0.16.9"
|
|
81
81
|
target-version = "py310"
|
|
82
82
|
|
|
83
83
|
[tool.ruff.analyze]
|
|
@@ -95,17 +95,12 @@ ignore = [
|
|
|
95
95
|
"builtin-open",
|
|
96
96
|
"complex-structure",
|
|
97
97
|
"error-suffix-on-exception-name",
|
|
98
|
-
"implicit-namespace-package",
|
|
99
98
|
"import-outside-top-level",
|
|
100
99
|
"incorrect-blank-line-before-class",
|
|
101
100
|
"meta-class-abc-meta",
|
|
102
101
|
"multi-line-summary-second-line",
|
|
103
102
|
"non-empty-init-module",
|
|
104
103
|
"os-replace",
|
|
105
|
-
"too-many-branches",
|
|
106
|
-
"too-many-locals",
|
|
107
|
-
"too-many-statements",
|
|
108
|
-
"unnecessary-dunder-call",
|
|
109
104
|
]
|
|
110
105
|
preview = true
|
|
111
106
|
select = ["ALL"]
|
|
@@ -115,6 +110,9 @@ docstring-quotes = "double"
|
|
|
115
110
|
inline-quotes = "single"
|
|
116
111
|
multiline-quotes = "double"
|
|
117
112
|
|
|
113
|
+
[tool.ruff.lint.flake8-annotations]
|
|
114
|
+
mypy-init-return = true
|
|
115
|
+
|
|
118
116
|
[tool.ruff.lint.isort]
|
|
119
117
|
combine-as-imports = true
|
|
120
118
|
|
|
@@ -123,20 +121,18 @@ combine-as-imports = true
|
|
|
123
121
|
"D",
|
|
124
122
|
"missing-type-args",
|
|
125
123
|
]
|
|
124
|
+
"!check_empty/__init__.py" = ["missing-copyright-notice"]
|
|
125
|
+
"check_empty/__init__.py" = ["PLR"]
|
|
126
|
+
"check_empty/__main__.py" = ["missing-return-type-private-function"]
|
|
127
|
+
"docs/source/conf.py" = ["implicit-namespace-package"]
|
|
126
128
|
"test_check_empty.py" = [
|
|
127
129
|
"ANN",
|
|
128
130
|
"D",
|
|
129
131
|
]
|
|
130
|
-
"!check_empty/__init__.py" = ["missing-copyright-notice"]
|
|
131
|
-
"check_empty/__main__.py" = ["missing-return-type-private-function"]
|
|
132
132
|
|
|
133
133
|
[tool.ruff.lint.pydocstyle]
|
|
134
134
|
convention = "google"
|
|
135
135
|
|
|
136
|
-
[tool.ruff.lint.pylint]
|
|
137
|
-
max-args = 6
|
|
138
|
-
max-nested-blocks = 6
|
|
139
|
-
|
|
140
136
|
[tool.ty.analysis]
|
|
141
137
|
respect-type-ignore-comments = false
|
|
142
138
|
|
|
@@ -157,7 +153,7 @@ redundant-condition = "ignore"
|
|
|
157
153
|
unsound-assignment = "ignore"
|
|
158
154
|
|
|
159
155
|
[tool.uv]
|
|
160
|
-
required-version = ">=0.12.
|
|
156
|
+
required-version = ">=0.12.19"
|
|
161
157
|
|
|
162
158
|
[tool.uv.build-backend]
|
|
163
159
|
module-name = "check_empty"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.12.
|
|
2
|
+
requires = ["uv_build>=0.12.19"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[dependency-groups]
|
|
@@ -16,12 +16,12 @@ maintainers = [{name = "Jonathan Dung", email = "jonathandung@yahoo.com"}]
|
|
|
16
16
|
name = "check-empty"
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
requires-python = ">=3.10"
|
|
19
|
-
version = "
|
|
19
|
+
version = "3.0.0"
|
|
20
20
|
|
|
21
21
|
[project.optional-dependencies]
|
|
22
22
|
"7z" = ["py7zr==1.1.3"]
|
|
23
23
|
ace = ["acefile==0.6.14"]
|
|
24
|
-
all = ["check-empty[7z,ace,ar,lzh,rar]==
|
|
24
|
+
all = ["check-empty[7z,ace,ar,lzh,rar]==3.0.0"]
|
|
25
25
|
ar = ["arpy==2.4.0"]
|
|
26
26
|
lzh = ["lhafile==0.3.1"]
|
|
27
27
|
rar = ["rarfile==4.5"]
|
|
@@ -30,7 +30,7 @@ rar = ["rarfile==4.5"]
|
|
|
30
30
|
check-empty = "check_empty.__main__:main"
|
|
31
31
|
|
|
32
32
|
[tool.ruff]
|
|
33
|
-
required-version = ">=0.16.
|
|
33
|
+
required-version = ">=0.16.9"
|
|
34
34
|
target-version = "py310"
|
|
35
35
|
|
|
36
36
|
[tool.ruff.analyze]
|
|
@@ -40,7 +40,7 @@ type-checking-imports = false
|
|
|
40
40
|
quote-style = "single"
|
|
41
41
|
|
|
42
42
|
[tool.ruff.lint]
|
|
43
|
-
ignore = ["COM", "FBT", "PT", "bad-quotes-inline-string", "builtin-open", "complex-structure", "error-suffix-on-exception-name", "
|
|
43
|
+
ignore = ["COM", "FBT", "PT", "bad-quotes-inline-string", "builtin-open", "complex-structure", "error-suffix-on-exception-name", "import-outside-top-level", "incorrect-blank-line-before-class", "meta-class-abc-meta", "multi-line-summary-second-line", "non-empty-init-module", "os-replace"]
|
|
44
44
|
preview = true
|
|
45
45
|
select = ["ALL"]
|
|
46
46
|
|
|
@@ -49,22 +49,23 @@ docstring-quotes = "double"
|
|
|
49
49
|
inline-quotes = "single"
|
|
50
50
|
multiline-quotes = "double"
|
|
51
51
|
|
|
52
|
+
[tool.ruff.lint.flake8-annotations]
|
|
53
|
+
mypy-init-return = true
|
|
54
|
+
|
|
52
55
|
[tool.ruff.lint.isort]
|
|
53
56
|
combine-as-imports = true
|
|
54
57
|
|
|
55
58
|
[tool.ruff.lint.per-file-ignores]
|
|
56
59
|
"action.py" = ["D", "missing-type-args"]
|
|
57
|
-
"test_check_empty.py" = ["ANN", "D"]
|
|
58
60
|
"!check_empty/__init__.py" = ["missing-copyright-notice"]
|
|
61
|
+
"check_empty/__init__.py" = ["PLR"]
|
|
59
62
|
"check_empty/__main__.py" = ["missing-return-type-private-function"]
|
|
63
|
+
"docs/source/conf.py" = ["implicit-namespace-package"]
|
|
64
|
+
"test_check_empty.py" = ["ANN", "D"]
|
|
60
65
|
|
|
61
66
|
[tool.ruff.lint.pydocstyle]
|
|
62
67
|
convention = "google"
|
|
63
68
|
|
|
64
|
-
[tool.ruff.lint.pylint]
|
|
65
|
-
max-args = 6
|
|
66
|
-
max-nested-blocks = 6
|
|
67
|
-
|
|
68
69
|
[tool.ty.analysis]
|
|
69
70
|
respect-type-ignore-comments = false
|
|
70
71
|
|
|
@@ -81,7 +82,7 @@ include = ["check_empty/__init__.py"]
|
|
|
81
82
|
rules = {possibly-unresolved-reference = "ignore", redundant-condition = "ignore", unsound-assignment = "ignore"}
|
|
82
83
|
|
|
83
84
|
[tool.uv]
|
|
84
|
-
required-version = ">=0.12.
|
|
85
|
+
required-version = ">=0.12.19"
|
|
85
86
|
|
|
86
87
|
[tool.uv.build-backend]
|
|
87
88
|
module-name = "check_empty"
|
|
File without changes
|
|
File without changes
|
|
@@ -4,9 +4,6 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import check_empty as c
|
|
6
6
|
|
|
7
|
-
TYPE_CHECKING = False
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from collections.abc import Iterable
|
|
10
7
|
__all__ = ('main',)
|
|
11
8
|
_p = __import__('argparse').ArgumentParser(
|
|
12
9
|
'check-empty',
|
|
@@ -43,6 +40,9 @@ f('-a', '--ar', action='store_true', help='recurse into .a, .ar and .lib archive
|
|
|
43
40
|
f('-7', '--7z', action='store_true', dest='z7', help='recurse into .7z archives')
|
|
44
41
|
f('-l', '--lzh', action='store_true', help='recurse into .lzh and .lha archives')
|
|
45
42
|
f('-A', '--ace', action='store_true', help='recurse into .ace archives')
|
|
43
|
+
TYPE_CHECKING = False
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from collections.abc import Iterable
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
def _r():
|
|
@@ -4,9 +4,6 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
|
|
7
|
-
TYPE_CHECKING = False
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from typing import Final
|
|
10
7
|
__all__ = (
|
|
11
8
|
'DIRFD_UNSUPPORTED',
|
|
12
9
|
'ENOENT',
|
|
@@ -15,6 +12,9 @@ __all__ = (
|
|
|
15
12
|
'TYPE_MASK',
|
|
16
13
|
'RecurseInto',
|
|
17
14
|
)
|
|
15
|
+
TYPE_CHECKING = False
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from typing import Final
|
|
18
18
|
TYPE_MASK: Final = 0xF000
|
|
19
19
|
"""This mask extracts the type of a file from its mode bits from :func:`os.stat`."""
|
|
20
20
|
S_IFDIR: Final = 0x4000
|
|
File without changes
|