end-of-file-fixer 0.2.0__py3-none-any.whl

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.

File without changes
@@ -0,0 +1,86 @@
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], check: bool) -> int: # noqa: C901
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
+ if not check:
22
+ # Needs this seek for windows, otherwise IOError
23
+ file_obj.seek(0, os.SEEK_END)
24
+ file_obj.write(b"\n")
25
+ return 1
26
+
27
+ while last_character in {b"\n", b"\r"}:
28
+ # Deal with the beginning of the file
29
+ if file_obj.tell() == 1:
30
+ if not check:
31
+ # If we've reached the beginning of the file and it is all
32
+ # linebreaks then we can make this file empty
33
+ file_obj.seek(0)
34
+ file_obj.truncate()
35
+ return 1
36
+
37
+ # Go back two bytes and read a character
38
+ file_obj.seek(-2, os.SEEK_CUR)
39
+ last_character = file_obj.read(1)
40
+
41
+ # Our current position is at the end of the file just before any amount of
42
+ # newlines. If we find extraneous newlines, then backtrack and trim them.
43
+ position = file_obj.tell()
44
+ remaining = file_obj.read()
45
+ for sequence in (b"\n", b"\r\n", b"\r"):
46
+ if remaining == sequence:
47
+ return 0
48
+
49
+ if remaining.startswith(sequence):
50
+ if not check:
51
+ file_obj.seek(position + len(sequence))
52
+ file_obj.truncate()
53
+ return 1
54
+
55
+ return 0 # pragma: no cover
56
+
57
+
58
+ def main() -> int:
59
+ parser = argparse.ArgumentParser()
60
+ parser.add_argument("path", help="path to directory", type=pathlib.Path)
61
+ parser.add_argument("--check", action="store_true")
62
+ args = parser.parse_args()
63
+
64
+ path: pathlib.Path = args.path
65
+ check: bool = args.check
66
+ gitignore_path = path / ".gitignore"
67
+
68
+ ignore_patterns = [
69
+ ".git",
70
+ ".cache", # for uv cache
71
+ ]
72
+ if gitignore_path.exists():
73
+ with gitignore_path.open("r") as f:
74
+ ignore_patterns.extend(f.readlines())
75
+
76
+ gitignore_spec = pathspec.GitIgnoreSpec.from_lines(ignore_patterns)
77
+
78
+ retv = 0
79
+ for filename in gitignore_spec.match_tree(path, negate=True):
80
+ with pathlib.Path(filename).open("rb+") as f:
81
+ ret_for_file = _fix_file(f, check=check)
82
+ if ret_for_file:
83
+ sys.stdout.write(f"Fixing {filename}")
84
+ retv |= ret_for_file
85
+
86
+ return retv
File without changes
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.3
2
+ Name: end-of-file-fixer
3
+ Version: 0.2.0
4
+ Summary: A command-line tool that ensures all your text files end with exactly one newline character
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
21
+
22
+ A command-line tool that ensures all your text files end with exactly one newline character.
23
+ This tool helps maintain consistent file formatting across your codebase by automatically adding or removing trailing newlines as needed.
24
+
25
+ ## Why This Matters
26
+
27
+ Many POSIX systems expect text files to end with a newline character. Having consistent line endings:
28
+ - Prevents spurious diffs in version control
29
+ - Ensures proper concatenation of files
30
+ - Satisfies POSIX compliance
31
+ - Improves readability in terminal environments
32
+
33
+ ## Features
34
+
35
+ - Automatically adds a newline to files that don't end with one
36
+ - Removes excess trailing newlines from files that have too many
37
+ - Respects `.gitignore` patterns to avoid processing unwanted files
38
+ - Works with all text file types
39
+ - Cross-platform compatibility (Windows, macOS, Linux)
40
+ - Dry-run mode to preview changes before applying them
41
+
42
+ ## Installation
43
+
44
+ ### Using uv
45
+
46
+ ```bash
47
+ uv add end-of-file-fixer
48
+ ```
49
+
50
+ ### Using pip
51
+
52
+ ```bash
53
+ pip install end-of-file-fixer
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### Basic Usage
59
+
60
+ To fix all files in the current directory and subdirectories:
61
+
62
+ ```bash
63
+ end-of-file-fixer .
64
+ ```
65
+
66
+ To check which files would be modified without making changes:
67
+
68
+ ```bash
69
+ end-of-file-fixer . --check
70
+ ```
71
+
72
+ ## How It Works
73
+
74
+ The end-of-file-fixer processes files in the following way:
75
+
76
+ 1. **Files with no trailing newline**: Adds exactly one newline at the end
77
+ 2. **Files with exactly one trailing newline**: Leaves unchanged
78
+ 3. **Files with multiple trailing newlines**: Truncates to exactly one newline
79
+ 4. **Empty files**: Left unchanged
80
+
81
+ ### Examples
82
+
83
+ | Original File Content | After Processing |
84
+ |----------------------|------------------|
85
+ | `hello world` | `hello world\n` |
86
+ | `hello world\n` | `hello world\n` |
87
+ | `hello world\n\n\n` | `hello world\n` |
88
+ | `` (empty file) | `` (unchanged) |
89
+
90
+ ## Configuration
91
+
92
+ The tool automatically respects patterns in your `.gitignore` file, so it won't process files that are ignored by Git. Additionally, it always ignores:
93
+ - `.git` directories
94
+ - `.cache` directories (used by uv)
95
+
96
+ ## Exit Codes
97
+
98
+ - `0`: No files needed fixing or all files were successfully fixed
99
+ - `1`: Some files needed fixing (when using `--check` mode)
100
+
101
+ ## Development
102
+
103
+ ### Prerequisites
104
+
105
+ - [uv](https://docs.astral.sh/uv/) for dependency management
106
+
107
+ ### Setup
108
+
109
+ ```bash
110
+ # Clone the repository
111
+ git clone https://github.com/community-of-python/end-of-file-fixer.git
112
+ cd end-of-file-fixer
113
+
114
+ # Install dependencies
115
+ just install
116
+ ```
117
+
118
+ ### Running Tests
119
+
120
+ ```bash
121
+ # Run tests
122
+ just test
123
+ ```
124
+
125
+ ### Linting
126
+
127
+ ```bash
128
+ # Run linting and formatting
129
+ just lint
130
+ ```
131
+
132
+ ## Contributing
133
+
134
+ Contributions are welcome! Please feel free to submit a Pull Request.
135
+
136
+ 1. Fork the repository
137
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
138
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
139
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
140
+ 5. Open a Pull Request
141
+
142
+ ## License
143
+
144
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
145
+
146
+ ## Related Projects
147
+
148
+ - [pre-commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks
149
+ - [editorconfig](https://editorconfig.org/) - Helps maintain consistent coding styles across different editors and IDEs
@@ -0,0 +1,7 @@
1
+ end_of_file_fixer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ end_of_file_fixer/main.py,sha256=hNOIMn1VnyOCrJxgD282oQf2ysPMWmC2CjU_tLIlAQY,2642
3
+ end_of_file_fixer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ end_of_file_fixer-0.2.0.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
5
+ end_of_file_fixer-0.2.0.dist-info/entry_points.txt,sha256=lWWJAZZZCdywSw18S88GIuafdBCnFgeepUtdioBUu4c,67
6
+ end_of_file_fixer-0.2.0.dist-info/METADATA,sha256=247R_Rg8Pp50SDLLcNM7tN1A3UWegXfCa7YnScoToTQ,4169
7
+ end_of_file_fixer-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.9.8
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ end-of-file-fixer = end_of_file_fixer.main:main
3
+