end-of-file-fixer 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.

Potentially problematic release.


This version of end-of-file-fixer might be problematic. Click here for more details.

@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.3
2
+ Name: end-of-file-fixer
3
+ Version: 0.1.0
4
+ Summary: Implementations of the Circuit Breaker
5
+ Keywords: python
6
+ Author: community-of-python
7
+ Classifier: Typing :: Typed
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: pathspec
14
+ Requires-Python: >=3.10, <4
15
+ Project-URL: Changelogs, https://github.com/community-of-python/end-of-file-fixer/releases
16
+ Project-URL: Issues, https://github.com/community-of-python/end-of-file-fixer/issues
17
+ Project-URL: Repository, https://github.com/community-of-python/end-of-file-fixer
18
+ Description-Content-Type: text/markdown
19
+
20
+ # End Of File Fixer
@@ -0,0 +1 @@
1
+ # End Of File Fixer
File without changes
@@ -0,0 +1,77 @@
1
+ import argparse
2
+ import os
3
+ import pathlib
4
+ import sys
5
+ from typing import IO
6
+
7
+ import pathspec
8
+
9
+
10
+ def _fix_file(file_obj: IO[bytes]) -> int:
11
+ # Test for newline at end of file
12
+ # Empty files will throw IOError here
13
+ try:
14
+ file_obj.seek(-1, os.SEEK_END)
15
+ except OSError:
16
+ return 0
17
+
18
+ last_character = file_obj.read(1)
19
+ # last_character will be '' for an empty file
20
+ if last_character not in {b"\n", b"\r"} and last_character != b"":
21
+ # Needs this seek for windows, otherwise IOError
22
+ file_obj.seek(0, os.SEEK_END)
23
+ file_obj.write(b"\n")
24
+ return 1
25
+
26
+ while last_character in {b"\n", b"\r"}:
27
+ # Deal with the beginning of the file
28
+ if file_obj.tell() == 1:
29
+ # If we've reached the beginning of the file and it is all
30
+ # linebreaks then we can make this file empty
31
+ file_obj.seek(0)
32
+ file_obj.truncate()
33
+ return 1
34
+
35
+ # Go back two bytes and read a character
36
+ file_obj.seek(-2, os.SEEK_CUR)
37
+ last_character = file_obj.read(1)
38
+
39
+ # Our current position is at the end of the file just before any amount of
40
+ # newlines. If we find extraneous newlines, then backtrack and trim them.
41
+ position = file_obj.tell()
42
+ remaining = file_obj.read()
43
+ for sequence in (b"\n", b"\r\n", b"\r"):
44
+ if remaining == sequence:
45
+ return 0
46
+ if remaining.startswith(sequence):
47
+ file_obj.seek(position + len(sequence))
48
+ file_obj.truncate()
49
+ return 1
50
+
51
+ return 0
52
+
53
+
54
+ def main() -> int:
55
+ parser = argparse.ArgumentParser()
56
+ parser.add_argument("path", help="path to directory", type=pathlib.Path)
57
+ args = parser.parse_args()
58
+
59
+ path: pathlib.Path = args.path
60
+ gitignore_path = path / ".gitignore"
61
+
62
+ ignore_patterns = [".git"]
63
+ if gitignore_path.exists():
64
+ with gitignore_path.open("r") as f:
65
+ ignore_patterns.extend(f.readlines())
66
+
67
+ gitignore_spec = pathspec.GitIgnoreSpec.from_lines(ignore_patterns)
68
+
69
+ retv = 0
70
+ for filename in gitignore_spec.match_tree(path, negate=True):
71
+ with pathlib.Path(filename).open("rb+") as f:
72
+ ret_for_file = _fix_file(f)
73
+ if ret_for_file:
74
+ sys.stdout.write(f"Fixing {filename}")
75
+ retv |= ret_for_file
76
+
77
+ return retv
File without changes
@@ -0,0 +1,77 @@
1
+ [project]
2
+ name = "end-of-file-fixer"
3
+ description = "Implementations of the Circuit Breaker"
4
+ readme = "README.md"
5
+ requires-python = ">=3.10,<4"
6
+ dependencies = [
7
+ "pathspec",
8
+ ]
9
+ version = "0.1.0"
10
+ authors = [{ name = "community-of-python" }]
11
+ keywords = [
12
+ "python",
13
+ ]
14
+ classifiers = [
15
+ "Typing :: Typed",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ ]
22
+
23
+ [project.urls]
24
+ Repository = "https://github.com/community-of-python/end-of-file-fixer"
25
+ Issues = "https://github.com/community-of-python/end-of-file-fixer/issues"
26
+ Changelogs = "https://github.com/community-of-python/end-of-file-fixer/releases"
27
+
28
+ [project.scripts]
29
+ end-of-file-fixer = "end_of_file_fixer.main:main"
30
+
31
+ [dependency-groups]
32
+ dev = [
33
+ "ruff",
34
+ "mypy",
35
+ "pytest",
36
+ "pytest-cov",
37
+ ]
38
+
39
+ [build-system]
40
+ requires = ["uv_build"]
41
+ build-backend = "uv_build"
42
+
43
+ [tool.uv.build-backend]
44
+ module-name = "end_of_file_fixer"
45
+ module-root = ""
46
+
47
+ [tool.mypy]
48
+ python_version = "3.10"
49
+ strict = true
50
+
51
+ [tool.ruff]
52
+ fix = true
53
+ unsafe-fixes = true
54
+ line-length = 120
55
+ target-version = "py310"
56
+
57
+ [tool.ruff.lint]
58
+ select = ["ALL"]
59
+ ignore = [
60
+ "D1", # allow missing docstrings
61
+ "S101", # allow asserts
62
+ "TCH", # ignore flake8-type-checking
63
+ "FBT", # allow boolean args
64
+ "D203", # "one-blank-line-before-class" conflicting with D211
65
+ "D213", # "multi-line-summary-second-line" conflicting with D212
66
+ "COM812", # flake8-commas "Trailing comma missing"
67
+ "ISC001", # flake8-implicit-str-concat
68
+ ]
69
+ isort.lines-after-imports = 2
70
+ isort.no-lines-before = ["standard-library", "local-folder"]
71
+
72
+ [tool.pytest.ini_options]
73
+ addopts = "--cov=. --cov-report term-missing"
74
+
75
+ [tool.coverage]
76
+ run.concurrency = ["thread"]
77
+ report.exclude_also = ["if typing.TYPE_CHECKING:"]