check-empty 0.1.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-0.1.0/AUTHORS.md +13 -0
- check_empty-0.1.0/LICENSE +21 -0
- check_empty-0.1.0/PKG-INFO +111 -0
- check_empty-0.1.0/README.md +77 -0
- check_empty-0.1.0/check_empty/__init__.py +9 -0
- check_empty-0.1.0/check_empty/__main__.py +83 -0
- check_empty-0.1.0/pyproject.toml +61 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jonathan Dung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: check-empty
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Command-line utility, as well as a hook usable by the Python pre-commit framework, to ensure that selected files are empty.
|
|
5
|
+
Keywords: check,command-line,empty,github-action,hook,lightweight,pre-commit,prek,tool,utility
|
|
6
|
+
Author: Jonathan Dung
|
|
7
|
+
Author-email: Jonathan Dung <jonathandung@yahoo.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: AUTHORS.md
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Natural Language :: English
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
27
|
+
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
|
28
|
+
Classifier: Topic :: Utilities
|
|
29
|
+
Classifier: Typing :: Typed
|
|
30
|
+
Maintainer: Jonathan Dung
|
|
31
|
+
Maintainer-email: Jonathan Dung <jonathandung@yahoo.com>
|
|
32
|
+
Requires-Python: >=3.7
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# check-empty
|
|
36
|
+
|
|
37
|
+
A simple [pre-commit](https://pre-commit.com)/[prek](https://prek.j178.dev) hook that
|
|
38
|
+
makes sure selected files are empty according to a filesystem stat call and clears them
|
|
39
|
+
effectively on demand with a write-mode open and immediate close. Also acts as a CLI,
|
|
40
|
+
library and GitHub Action conglomerate.
|
|
41
|
+
|
|
42
|
+
## Quickstart
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv tool install check-empty # uv
|
|
46
|
+
pip install check-empty # pip
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Check the version with:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
check-empty -v
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Run the CLI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
check-empty -q src/mylib/py.typed docs/.nojekyll static/.gitkeep
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
As a pre-commit hook:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# .pre-commit-config.yaml
|
|
65
|
+
repos:
|
|
66
|
+
- repo: https://github.com/jonathandung/check-empty
|
|
67
|
+
rev: v0.1.0 # repository version
|
|
68
|
+
hooks:
|
|
69
|
+
- id: check-empty # the hook
|
|
70
|
+
args: # example list of arguments
|
|
71
|
+
- --quiet # flag to silence output (equivalent to -q)
|
|
72
|
+
# below: paths to files to clear or keep empty, either relative to the project
|
|
73
|
+
# root or absolute (not shown)
|
|
74
|
+
- src/mylib/py.typed
|
|
75
|
+
- docs/.nojekyll
|
|
76
|
+
- static/.gitkeep
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
equivalent in `prek.toml` format:
|
|
80
|
+
|
|
81
|
+
```toml
|
|
82
|
+
[[repos]]
|
|
83
|
+
repo = "https://github.com/jonathandung/check-empty"
|
|
84
|
+
rev = "v0.1.0"
|
|
85
|
+
hooks = [{
|
|
86
|
+
id = "check-empty",
|
|
87
|
+
args = [
|
|
88
|
+
"--quiet",
|
|
89
|
+
"src/mylib/py.typed",
|
|
90
|
+
"docs/.nojekyll",
|
|
91
|
+
"static/.gitkeep",
|
|
92
|
+
]
|
|
93
|
+
}]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
As a GitHub action step:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
steps:
|
|
100
|
+
- uses: jonathandung/check-empty@v0.1.0 # the latest version on the GitHub Actions
|
|
101
|
+
# marketplace; this step will fail and subsequent jobs will not run if any file is
|
|
102
|
+
# not empty
|
|
103
|
+
with:
|
|
104
|
+
python-version: '3.14' # run the script on the latest stable Python version
|
|
105
|
+
# Python down to 3.6 is supported but not recommended due to end-of-life
|
|
106
|
+
quiet: true
|
|
107
|
+
filenames: |
|
|
108
|
+
src/mylib/py.typed
|
|
109
|
+
docs/.nojekyll
|
|
110
|
+
static/.gitkeep
|
|
111
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# check-empty
|
|
2
|
+
|
|
3
|
+
A simple [pre-commit](https://pre-commit.com)/[prek](https://prek.j178.dev) hook that
|
|
4
|
+
makes sure selected files are empty according to a filesystem stat call and clears them
|
|
5
|
+
effectively on demand with a write-mode open and immediate close. Also acts as a CLI,
|
|
6
|
+
library and GitHub Action conglomerate.
|
|
7
|
+
|
|
8
|
+
## Quickstart
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv tool install check-empty # uv
|
|
12
|
+
pip install check-empty # pip
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Check the version with:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
check-empty -v
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Run the CLI:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
check-empty -q src/mylib/py.typed docs/.nojekyll static/.gitkeep
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
As a pre-commit hook:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
# .pre-commit-config.yaml
|
|
31
|
+
repos:
|
|
32
|
+
- repo: https://github.com/jonathandung/check-empty
|
|
33
|
+
rev: v0.1.0 # repository version
|
|
34
|
+
hooks:
|
|
35
|
+
- id: check-empty # the hook
|
|
36
|
+
args: # example list of arguments
|
|
37
|
+
- --quiet # flag to silence output (equivalent to -q)
|
|
38
|
+
# below: paths to files to clear or keep empty, either relative to the project
|
|
39
|
+
# root or absolute (not shown)
|
|
40
|
+
- src/mylib/py.typed
|
|
41
|
+
- docs/.nojekyll
|
|
42
|
+
- static/.gitkeep
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
equivalent in `prek.toml` format:
|
|
46
|
+
|
|
47
|
+
```toml
|
|
48
|
+
[[repos]]
|
|
49
|
+
repo = "https://github.com/jonathandung/check-empty"
|
|
50
|
+
rev = "v0.1.0"
|
|
51
|
+
hooks = [{
|
|
52
|
+
id = "check-empty",
|
|
53
|
+
args = [
|
|
54
|
+
"--quiet",
|
|
55
|
+
"src/mylib/py.typed",
|
|
56
|
+
"docs/.nojekyll",
|
|
57
|
+
"static/.gitkeep",
|
|
58
|
+
]
|
|
59
|
+
}]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
As a GitHub action step:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
steps:
|
|
66
|
+
- uses: jonathandung/check-empty@v0.1.0 # the latest version on the GitHub Actions
|
|
67
|
+
# marketplace; this step will fail and subsequent jobs will not run if any file is
|
|
68
|
+
# not empty
|
|
69
|
+
with:
|
|
70
|
+
python-version: '3.14' # run the script on the latest stable Python version
|
|
71
|
+
# Python down to 3.6 is supported but not recommended due to end-of-life
|
|
72
|
+
quiet: true
|
|
73
|
+
filenames: |
|
|
74
|
+
src/mylib/py.typed
|
|
75
|
+
docs/.nojekyll
|
|
76
|
+
static/.gitkeep
|
|
77
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright © 2026 Jonathan Dung. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""Utility to check the emptiness of files.
|
|
4
|
+
|
|
5
|
+
Pre-commit hook, command-line tool and GitHub Action all-in-one.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__all__ = ('main',)
|
|
9
|
+
from check_empty.__main__ import __version__ as __version__, main
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!usr/bin/env python3
|
|
2
|
+
"""Implementation of the main routine."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from os.path import getsize
|
|
7
|
+
|
|
8
|
+
TYPE_CHECKING = False
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from typing import Literal, Sequence
|
|
11
|
+
|
|
12
|
+
__version__ = '0.1'
|
|
13
|
+
parser = __import__('argparse').ArgumentParser(
|
|
14
|
+
'check-empty',
|
|
15
|
+
description='Assert or enforce that some files are empty.',
|
|
16
|
+
epilog='It is preferred that you use this as a pre-commit/prek hook or GitHub '
|
|
17
|
+
'Action for most cases which are not one-off.',
|
|
18
|
+
)
|
|
19
|
+
f = parser.add_argument
|
|
20
|
+
f('filenames', nargs='+', help='the files that should be empty')
|
|
21
|
+
f('-v', '--version', action='version', version='check-empty v' + __version__)
|
|
22
|
+
f('-c', '--clear', action='store_true', help='clear files that are not empty')
|
|
23
|
+
f('-m', '--must-exist', action='store_true', help='fail if any file is absent')
|
|
24
|
+
f('-q', '--quiet', action='store_true', help='suppress output')
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def main(argv: Sequence[str] | None = None) -> Literal[0, 1, 2, 3]:
|
|
28
|
+
"""Run the hook on the files in the (command-line) arguments passed.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
argv: A list of arguments excluding the executable name, default sys.argv[1:].
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
The exit code. A bitwise or of 1 (some files were not empty) and 2 (some files
|
|
35
|
+
were absent and --must-exist was specified), such that 0 is the only return
|
|
36
|
+
value that represents success as expected.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
r, z, n = [''], [''], parser.parse_args(argv)
|
|
40
|
+
g, j, c, t, i = r.append, z.append, n.clear, 0, n.filenames
|
|
41
|
+
if c:
|
|
42
|
+
for a in i:
|
|
43
|
+
try:
|
|
44
|
+
s = getsize(a)
|
|
45
|
+
except FileNotFoundError:
|
|
46
|
+
j(a)
|
|
47
|
+
continue
|
|
48
|
+
if not s:
|
|
49
|
+
continue
|
|
50
|
+
g(f'{a} ({s} bytes)')
|
|
51
|
+
t += s
|
|
52
|
+
with open(a, 'wb'):
|
|
53
|
+
...
|
|
54
|
+
else:
|
|
55
|
+
for a in i:
|
|
56
|
+
try:
|
|
57
|
+
s = getsize(a)
|
|
58
|
+
except FileNotFoundError:
|
|
59
|
+
j(a)
|
|
60
|
+
continue
|
|
61
|
+
if not s:
|
|
62
|
+
continue
|
|
63
|
+
g(f'{a} ({s} bytes)')
|
|
64
|
+
t += s
|
|
65
|
+
p, x, y = not n.quiet, len(z) - 1, len(r) - 1
|
|
66
|
+
v = n.must_exist << 1 if x else 0
|
|
67
|
+
if p:
|
|
68
|
+
print(*z, sep='\nNot found: ')
|
|
69
|
+
print(f'{x} files not found' if x else 'All files were found')
|
|
70
|
+
if y:
|
|
71
|
+
if p:
|
|
72
|
+
print(*r, sep='\nCleared: ' if c else '\nNot empty: ', end='\n\n')
|
|
73
|
+
print(y, 'offending files' if y > 1 else 'offending file')
|
|
74
|
+
print(f'Total size: {t} bytes')
|
|
75
|
+
return v | 1
|
|
76
|
+
if p:
|
|
77
|
+
print('All found files were empty')
|
|
78
|
+
return v
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == '__main__':
|
|
82
|
+
raise SystemExit(main())
|
|
83
|
+
del f, TYPE_CHECKING
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.11.29,<0.12"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
authors = [{name = "Jonathan Dung", email = "jonathandung@yahoo.com"}]
|
|
7
|
+
classifiers = ["Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.15", "Programming Language :: Python :: Free Threading :: 3 - Stable", "Topic :: Utilities", "Typing :: Typed"]
|
|
8
|
+
description = "Command-line utility, as well as a hook usable by the Python pre-commit framework, to ensure that selected files are empty."
|
|
9
|
+
keywords = ["check", "command-line", "empty", "github-action", "hook", "lightweight", "pre-commit", "prek", "tool", "utility"]
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE", "AUTHORS.md"]
|
|
12
|
+
maintainers = [{name = "Jonathan Dung", email = "jonathandung@yahoo.com"}]
|
|
13
|
+
name = "check-empty"
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
requires-python = ">=3.7"
|
|
16
|
+
version = "0.1.0"
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
check-empty = "check_empty.__main__:main"
|
|
20
|
+
|
|
21
|
+
[tool.ruff]
|
|
22
|
+
target-version = "py37"
|
|
23
|
+
|
|
24
|
+
[tool.ruff.analyze]
|
|
25
|
+
type-checking-imports = false
|
|
26
|
+
|
|
27
|
+
[tool.ruff.format]
|
|
28
|
+
quote-style = "single"
|
|
29
|
+
|
|
30
|
+
[tool.ruff.lint]
|
|
31
|
+
ignore = ["ANN", "COM", "PT", "PTH", "avoidable-escaped-quote", "bad-quotes-inline-string", "complex-structure", "docstring-extraneous-exception", "incorrect-blank-line-before-class", "multi-line-summary-second-line", "print", "unnecessary-dunder-call"]
|
|
32
|
+
preview = true
|
|
33
|
+
select = ["ALL"]
|
|
34
|
+
|
|
35
|
+
[tool.ruff.lint.isort]
|
|
36
|
+
combine-as-imports = true
|
|
37
|
+
|
|
38
|
+
[tool.ruff.lint.per-file-ignores]
|
|
39
|
+
"test.py" = ["D"]
|
|
40
|
+
"!__init__.py" = ["missing-copyright-notice"]
|
|
41
|
+
|
|
42
|
+
[tool.ruff.lint.pydocstyle]
|
|
43
|
+
convention = "google"
|
|
44
|
+
|
|
45
|
+
[tool.ty.analysis]
|
|
46
|
+
respect-type-ignore-comments = false
|
|
47
|
+
|
|
48
|
+
[tool.ty.environment]
|
|
49
|
+
python-version = "3.7"
|
|
50
|
+
python-platform = "all"
|
|
51
|
+
|
|
52
|
+
[tool.ty.rules]
|
|
53
|
+
all = "error"
|
|
54
|
+
missing-override-decorator = "ignore"
|
|
55
|
+
|
|
56
|
+
[tool.uv]
|
|
57
|
+
required-version = ">=0.11.29,<0.12"
|
|
58
|
+
|
|
59
|
+
[tool.uv.build-backend]
|
|
60
|
+
module-name = "check_empty"
|
|
61
|
+
module-root = ""
|