whitespace-format 0.0.3__tar.gz → 0.0.4__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.
- {whitespace_format-0.0.3 → whitespace_format-0.0.4}/PKG-INFO +3 -4
- {whitespace_format-0.0.3 → whitespace_format-0.0.4}/README.md +2 -2
- {whitespace_format-0.0.3 → whitespace_format-0.0.4}/pyproject.toml +4 -4
- {whitespace_format-0.0.3 → whitespace_format-0.0.4}/whitespace_format.py +199 -89
- whitespace_format-0.0.3/setup.py +0 -25
- {whitespace_format-0.0.3 → whitespace_format-0.0.4}/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: whitespace-format
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.4
|
4
4
|
Summary: Linter and formatter for source code files and text files
|
5
5
|
Home-page: https://github.com/DavidPal/whitespace-format
|
6
6
|
License: MIT
|
@@ -14,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.8
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.9
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
18
17
|
Project-URL: Repository, https://github.com/DavidPal/whitespace-format
|
19
18
|
Description-Content-Type: text/markdown
|
20
19
|
|
@@ -22,7 +21,7 @@ Description-Content-Type: text/markdown
|
|
22
21
|
|
23
22
|
[](https://dl.circleci.com/status-badge/redirect/gh/DavidPal/whitespace-format/tree/main)
|
24
23
|
|
25
|
-
](https://github.com/DavidPal/whitespace-format/actions/workflows/build.yaml)
|
26
25
|
|
27
26
|
Linter and formatter for source code files and text files.
|
28
27
|
|
@@ -32,7 +31,7 @@ MarkDown, LaTeX) before checking them into a version control system.
|
|
32
31
|
|
33
32
|
The features include:
|
34
33
|
|
35
|
-
* Auto-detection of new line markers (Linux `\n`, Windows `\r\
|
34
|
+
* Auto-detection of new line markers (Linux `\n`, Windows `\r\n`, Mac `\r`).
|
36
35
|
* Add a new line marker at the end of the file if it is missing.
|
37
36
|
* Make new line markers consistent.
|
38
37
|
* Remove empty lines at the end of the file.
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://dl.circleci.com/status-badge/redirect/gh/DavidPal/whitespace-format/tree/main)
|
4
4
|
|
5
|
-
](https://github.com/DavidPal/whitespace-format/actions/workflows/build.yaml)
|
6
6
|
|
7
7
|
Linter and formatter for source code files and text files.
|
8
8
|
|
@@ -12,7 +12,7 @@ MarkDown, LaTeX) before checking them into a version control system.
|
|
12
12
|
|
13
13
|
The features include:
|
14
14
|
|
15
|
-
* Auto-detection of new line markers (Linux `\n`, Windows `\r\
|
15
|
+
* Auto-detection of new line markers (Linux `\n`, Windows `\r\n`, Mac `\r`).
|
16
16
|
* Add a new line marker at the end of the file if it is missing.
|
17
17
|
* Make new line markers consistent.
|
18
18
|
* Remove empty lines at the end of the file.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "whitespace-format"
|
3
|
-
version = "0.0.
|
3
|
+
version = "0.0.4"
|
4
4
|
description = "Linter and formatter for source code files and text files"
|
5
5
|
license = "MIT"
|
6
6
|
authors = ["David Pal <davidko.pal@gmail.com>"]
|
@@ -25,10 +25,10 @@ coverage = "^7.2.4"
|
|
25
25
|
flake8 = "^5.0.4"
|
26
26
|
flake8-absolute-import = "^1.0.0.1"
|
27
27
|
isort = {extras = ["colors"], version = "^5.11.5"}
|
28
|
-
mypy = "^1.
|
28
|
+
mypy = "^1.4.1"
|
29
29
|
pydocstyle = {extras = ["toml"], version = "^6.3.0"}
|
30
|
-
pytest = "^7.
|
31
|
-
pylint = "^2.
|
30
|
+
pytest = "^7.4.1"
|
31
|
+
pylint = "^2.17.5"
|
32
32
|
pylint-quotes = "^0.2.3"
|
33
33
|
|
34
34
|
[build-system]
|
@@ -10,22 +10,26 @@ Usage:
|
|
10
10
|
python whitespace_format.py [OPTIONS] [FILES ...]
|
11
11
|
"""
|
12
12
|
|
13
|
+
from __future__ import annotations
|
14
|
+
|
13
15
|
import argparse
|
16
|
+
import copy
|
14
17
|
import dataclasses
|
15
18
|
import pathlib
|
16
19
|
import re
|
17
20
|
import sys
|
18
21
|
from typing import Callable
|
22
|
+
from typing import Dict
|
19
23
|
from typing import List
|
20
24
|
|
21
|
-
VERSION = "0.0.
|
25
|
+
VERSION = "0.0.4"
|
22
26
|
|
23
27
|
# Regular expression that does NOT match any string.
|
24
28
|
UNMATCHABLE_REGEX = "$."
|
25
29
|
|
26
|
-
|
27
|
-
"linux": "\n",
|
30
|
+
END_OF_LINE_MARKERS = {
|
28
31
|
"windows": "\r\n",
|
32
|
+
"linux": "\n",
|
29
33
|
"mac": "\r",
|
30
34
|
}
|
31
35
|
|
@@ -96,99 +100,185 @@ def write_file(file_name: str, file_content: str, encoding: str):
|
|
96
100
|
die(4, f"Cannot write to file '{file_name}': {exception}")
|
97
101
|
|
98
102
|
|
99
|
-
|
100
|
-
|
103
|
+
@dataclasses.dataclass
|
104
|
+
class Line:
|
105
|
+
"""Line of a text file.
|
101
106
|
|
102
|
-
The
|
107
|
+
The line is split into two parts:
|
108
|
+
1) Content
|
109
|
+
2) End of line marker ("\n", or "\r", or "\r\n")
|
103
110
|
"""
|
104
|
-
windows_count = file_content.count("\r\n")
|
105
|
-
linux_count = file_content.count("\n") - windows_count
|
106
|
-
mac_count = file_content.count("\r") - windows_count
|
107
|
-
|
108
|
-
# Pick the new line marker with the highest count.
|
109
|
-
# Break ties according to the ordering: Linux > Windows > Mac.
|
110
|
-
_, _, new_line_marker_guess = max(
|
111
|
-
(linux_count, 3, "\n"),
|
112
|
-
(windows_count, 2, "\r\n"),
|
113
|
-
(mac_count, 1, "\r"),
|
114
|
-
)
|
115
111
|
|
116
|
-
|
112
|
+
content: str
|
113
|
+
end_of_line_marker: str
|
117
114
|
|
115
|
+
@staticmethod
|
116
|
+
def create_from_string(line: str) -> Line:
|
117
|
+
"""Creates a line from a string.
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
return
|
125
|
-
if file_content[i : i + 2] == "\r\n":
|
126
|
-
return file_content[: i + 2]
|
127
|
-
return file_content[: i + 1]
|
119
|
+
The function splits the input into content and end_of_line_marker.
|
120
|
+
"""
|
121
|
+
for end_of_line_marker in ["\r\n", "\n", "\r"]:
|
122
|
+
if line.endswith(end_of_line_marker):
|
123
|
+
return Line(line[: -len(end_of_line_marker)], end_of_line_marker)
|
124
|
+
return Line(line, "")
|
128
125
|
|
129
126
|
|
130
|
-
def
|
131
|
-
"""
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
127
|
+
def split_lines(text: str) -> List[Line]:
|
128
|
+
"""Splits a string into lines."""
|
129
|
+
lines: List[Line] = []
|
130
|
+
current_line = ""
|
131
|
+
for i, char in enumerate(text):
|
132
|
+
current_line += char
|
133
|
+
if (char == "\n") or (
|
134
|
+
(char == "\r") and ((i >= len(text) - 1) or (not text[i + 1] == "\n"))
|
135
|
+
):
|
136
|
+
lines.append(Line.create_from_string(current_line))
|
137
|
+
current_line = ""
|
136
138
|
|
139
|
+
if current_line:
|
140
|
+
lines.append(Line.create_from_string(current_line))
|
137
141
|
|
138
|
-
|
139
|
-
"""Removes all new line markers from the end of the file."""
|
140
|
-
return file_content.rstrip("\n\r")
|
142
|
+
return lines
|
141
143
|
|
142
144
|
|
143
|
-
def
|
144
|
-
"""
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
145
|
+
def concatenate_lines(lines: List[Line]) -> str:
|
146
|
+
"""Concatenates a list of lines into a single string including end-of-line markers."""
|
147
|
+
return "".join(line.content + line.end_of_line_marker for line in lines)
|
148
|
+
|
149
|
+
|
150
|
+
def guess_end_of_line_marker(lines: List[Line]) -> str:
|
151
|
+
"""Guesses the end of line marker.
|
152
|
+
|
153
|
+
The function returns the most common end-of-line marker.
|
154
|
+
Ties are broken in order Linux "\n", Mac "\r", Windows "\r\n".
|
155
|
+
If no end-of-line marker is present, default to the Linux "\n" end-of-line marker.
|
156
|
+
"""
|
157
|
+
counts: Dict[str, int] = {"\n": 0, "\r": 0, "\r\n": 0}
|
158
|
+
for line in lines:
|
159
|
+
if line.end_of_line_marker in counts:
|
160
|
+
counts[line.end_of_line_marker] += 1
|
161
|
+
max_count = max(counts.values())
|
162
|
+
for end_of_line_marker, count in counts.items():
|
163
|
+
if count == max_count:
|
164
|
+
return end_of_line_marker
|
165
|
+
return "\n" # This return statement is never executed.
|
166
|
+
|
167
|
+
|
168
|
+
def remove_trailing_empty_lines(lines: List[Line]) -> List[Line]:
|
169
|
+
"""Removes trailing empty lines.
|
170
|
+
|
171
|
+
If there are no lines, empty list is returned.
|
172
|
+
If all lines are empty, the first line is kept.
|
173
|
+
"""
|
174
|
+
num_empty_trailing_lines = 0
|
175
|
+
while (num_empty_trailing_lines < len(lines) - 1) and (
|
176
|
+
not lines[-num_empty_trailing_lines - 1].content
|
177
|
+
):
|
178
|
+
num_empty_trailing_lines += 1
|
179
|
+
return copy.deepcopy(lines[: len(lines) - num_empty_trailing_lines])
|
180
|
+
|
181
|
+
|
182
|
+
def remove_dummy_lines(lines: List[Line]) -> List[Line]:
|
183
|
+
"""Remove empty lines that also have empty end-of-line markers."""
|
184
|
+
return [line for line in lines if line.content or line.end_of_line_marker]
|
185
|
+
|
186
|
+
|
187
|
+
def remove_trailing_whitespace(lines: List[Line]) -> List[Line]:
|
188
|
+
"""Removes trailing whitespace from every line."""
|
189
|
+
lines = [
|
190
|
+
Line(
|
191
|
+
re.sub(r"[ \n\r\t\f\v]*$", "", line.content),
|
192
|
+
line.end_of_line_marker,
|
193
|
+
)
|
194
|
+
for line in lines
|
195
|
+
]
|
196
|
+
return remove_dummy_lines(lines)
|
197
|
+
|
198
|
+
|
199
|
+
def normalize_end_of_line_markers(lines: List[Line], new_end_of_line_marker: str) -> List[Line]:
|
200
|
+
"""Replaces end-of-line marker in all lines with a new end-of-line marker.
|
201
|
+
|
202
|
+
Lines without end-of-line markers (i.e. possibly the last line) are left unchanged.
|
203
|
+
"""
|
204
|
+
return [
|
205
|
+
Line(line.content, new_end_of_line_marker) if line.end_of_line_marker else line
|
206
|
+
for line in lines
|
207
|
+
]
|
150
208
|
|
151
209
|
|
152
|
-
def
|
153
|
-
"""
|
154
|
-
|
210
|
+
def remove_all_end_of_line_markers_from_end_of_file(lines: List[Line]) -> List[Line]:
|
211
|
+
"""Removes all end-of-line markers from the end of the file."""
|
212
|
+
lines = remove_trailing_empty_lines(lines)
|
213
|
+
if not lines:
|
214
|
+
return []
|
215
|
+
lines[-1] = Line(lines[-1].content, "")
|
216
|
+
return remove_dummy_lines(lines)
|
155
217
|
|
156
218
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
219
|
+
def add_end_of_line_marker_at_end_of_file(
|
220
|
+
lines: List[Line], new_end_of_line_marker: str
|
221
|
+
) -> List[Line]:
|
222
|
+
"""Adds new end-of-line marker to the end of file if it is missing."""
|
223
|
+
if not lines:
|
224
|
+
return [Line("", new_end_of_line_marker)]
|
225
|
+
lines = copy.deepcopy(lines)
|
226
|
+
lines[-1] = Line(lines[-1].content, new_end_of_line_marker)
|
227
|
+
return lines
|
162
228
|
|
163
229
|
|
164
|
-
def normalize_empty_file(
|
230
|
+
def normalize_empty_file(lines: List[Line], mode: str, new_end_of_line_marker: str) -> List[Line]:
|
165
231
|
"""Replaces file with an empty file."""
|
166
232
|
if mode == "empty":
|
167
|
-
return
|
233
|
+
return []
|
168
234
|
if mode == "one-line":
|
169
|
-
return
|
170
|
-
return
|
235
|
+
return [Line("", new_end_of_line_marker)]
|
236
|
+
return copy.deepcopy(lines)
|
171
237
|
|
172
238
|
|
173
|
-
def is_whitespace_only(
|
239
|
+
def is_whitespace_only(lines: List[Line]) -> bool:
|
174
240
|
"""Determines if file consists only of whitespace."""
|
175
|
-
|
241
|
+
for line in lines:
|
242
|
+
if line.content.strip(" \n\r\t\v\f"):
|
243
|
+
return False
|
244
|
+
return True
|
176
245
|
|
177
246
|
|
178
|
-
def normalize_non_standard_whitespace(
|
247
|
+
def normalize_non_standard_whitespace(lines: List[Line], mode: str) -> List[Line]:
|
179
248
|
"""Removes non-standard whitespace characters."""
|
180
249
|
if mode == "ignore":
|
181
|
-
return
|
250
|
+
return copy.deepcopy(lines)
|
182
251
|
if mode == "replace":
|
183
|
-
return
|
184
|
-
|
252
|
+
return [
|
253
|
+
Line(line.content.translate(str.maketrans("\v\f", " ", "")), line.end_of_line_marker)
|
254
|
+
for line in lines
|
255
|
+
]
|
256
|
+
return [
|
257
|
+
Line(line.content.translate(str.maketrans("", "", "\v\f")), line.end_of_line_marker)
|
258
|
+
for line in lines
|
259
|
+
]
|
185
260
|
|
186
261
|
|
187
|
-
def replace_tabs_with_spaces(
|
262
|
+
def replace_tabs_with_spaces(lines: List[Line], num_spaces: int) -> List[Line]:
|
188
263
|
"""Replaces tabs with spaces."""
|
189
264
|
if num_spaces < 0:
|
190
|
-
return
|
191
|
-
return
|
265
|
+
return copy.deepcopy(lines)
|
266
|
+
return [
|
267
|
+
Line(line.content.replace("\t", num_spaces * " "), line.end_of_line_marker)
|
268
|
+
for line in lines
|
269
|
+
]
|
270
|
+
|
271
|
+
|
272
|
+
def compute_difference(original_lines: List[Line], new_lines: List[Line]) -> List[int]:
|
273
|
+
"""Computes the indices of lines that differ."""
|
274
|
+
line_numbers = [
|
275
|
+
line_number
|
276
|
+
for line_number, (original_line, new_line) in enumerate(zip(original_lines, new_lines))
|
277
|
+
if not original_line == new_line
|
278
|
+
]
|
279
|
+
if len(original_lines) != len(new_lines):
|
280
|
+
line_numbers.append(min(len(original_lines), len(new_lines)))
|
281
|
+
return line_numbers
|
192
282
|
|
193
283
|
|
194
284
|
@dataclasses.dataclass
|
@@ -199,25 +289,36 @@ class ChangeDescription:
|
|
199
289
|
change: str
|
200
290
|
|
201
291
|
|
292
|
+
@dataclasses.dataclass
|
293
|
+
class LineChange:
|
294
|
+
"""Description of a change on a particular line."""
|
295
|
+
|
296
|
+
check_only: str
|
297
|
+
change: str
|
298
|
+
line_number: int
|
299
|
+
|
300
|
+
|
202
301
|
class FileContentTracker:
|
203
302
|
"""Tracks changes of the content of a file as it undergoes formatting."""
|
204
303
|
|
205
|
-
def __init__(self,
|
304
|
+
def __init__(self, lines: List[Line]):
|
206
305
|
"""Initializes an instance of the file content tracker."""
|
207
|
-
self.
|
208
|
-
self.
|
209
|
-
self.
|
306
|
+
self.initial_lines = lines
|
307
|
+
self.lines = copy.deepcopy(lines)
|
308
|
+
self.line_changes: List[LineChange] = []
|
210
309
|
|
211
|
-
def format(self, change: ChangeDescription, function: Callable[...,
|
310
|
+
def format(self, change: ChangeDescription, function: Callable[..., List[Line]], *args):
|
212
311
|
"""Applies a change to the content of the file."""
|
213
|
-
previous_content = self.
|
214
|
-
self.
|
215
|
-
if previous_content != self.
|
216
|
-
self.
|
312
|
+
previous_content = self.lines
|
313
|
+
self.lines = function(self.lines, *args)
|
314
|
+
if previous_content != self.lines:
|
315
|
+
line_numbers = compute_difference(previous_content, self.lines)
|
316
|
+
for line_number in line_numbers:
|
317
|
+
self.line_changes.append(LineChange(change.check_only, change.change, line_number))
|
217
318
|
|
218
319
|
def is_changed(self) -> bool:
|
219
320
|
"""Determines if the file content has changed."""
|
220
|
-
return self.
|
321
|
+
return self.lines != self.initial_lines
|
221
322
|
|
222
323
|
|
223
324
|
def format_file_content(
|
@@ -225,12 +326,12 @@ def format_file_content(
|
|
225
326
|
parsed_arguments: argparse.Namespace,
|
226
327
|
):
|
227
328
|
"""Formats the content of file represented as a string."""
|
228
|
-
new_line_marker =
|
329
|
+
new_line_marker = END_OF_LINE_MARKERS.get(
|
229
330
|
parsed_arguments.new_line_marker,
|
230
|
-
|
331
|
+
guess_end_of_line_marker(file_content_tracker.initial_lines),
|
231
332
|
)
|
232
333
|
|
233
|
-
if is_whitespace_only(file_content_tracker.
|
334
|
+
if is_whitespace_only(file_content_tracker.initial_lines):
|
234
335
|
changes = {
|
235
336
|
"ignore": ChangeDescription("", ""),
|
236
337
|
"empty": ChangeDescription(
|
@@ -246,7 +347,7 @@ def format_file_content(
|
|
246
347
|
),
|
247
348
|
),
|
248
349
|
}
|
249
|
-
if not file_content_tracker.
|
350
|
+
if not file_content_tracker.initial_lines:
|
250
351
|
file_content_tracker.format(
|
251
352
|
changes[parsed_arguments.normalize_empty_files],
|
252
353
|
normalize_empty_file,
|
@@ -265,8 +366,8 @@ def format_file_content(
|
|
265
366
|
if parsed_arguments.remove_trailing_whitespace:
|
266
367
|
file_content_tracker.format(
|
267
368
|
ChangeDescription(
|
268
|
-
check_only="Whitespace at the end of line
|
269
|
-
change="Whitespace at the end of line
|
369
|
+
check_only="Whitespace at the end of line needs to be removed.",
|
370
|
+
change="Whitespace at the end of line was removed.",
|
270
371
|
),
|
271
372
|
remove_trailing_whitespace,
|
272
373
|
)
|
@@ -308,7 +409,7 @@ def format_file_content(
|
|
308
409
|
),
|
309
410
|
change=f"New line marker(s) were replaced with {repr(new_line_marker)}.",
|
310
411
|
),
|
311
|
-
|
412
|
+
normalize_end_of_line_markers,
|
312
413
|
new_line_marker,
|
313
414
|
)
|
314
415
|
|
@@ -320,7 +421,7 @@ def format_file_content(
|
|
320
421
|
change=f"New line marker was added to the end of the file, "
|
321
422
|
f"or replaced with {repr(new_line_marker)}.",
|
322
423
|
),
|
323
|
-
|
424
|
+
add_end_of_line_marker_at_end_of_file,
|
324
425
|
new_line_marker,
|
325
426
|
)
|
326
427
|
elif parsed_arguments.remove_new_line_marker_from_end_of_file:
|
@@ -329,14 +430,15 @@ def format_file_content(
|
|
329
430
|
check_only="New line marker(s) need to removed from the end of the file.",
|
330
431
|
change="New line marker(s) were removed from the end of the file.",
|
331
432
|
),
|
332
|
-
|
433
|
+
remove_all_end_of_line_markers_from_end_of_file,
|
333
434
|
)
|
334
435
|
|
335
436
|
|
336
437
|
def reformat_file(file_name: str, parsed_arguments: argparse.Namespace) -> bool:
|
337
438
|
"""Reformats a file."""
|
338
439
|
file_content = read_file_content(file_name, parsed_arguments.encoding)
|
339
|
-
|
440
|
+
lines = split_lines(file_content)
|
441
|
+
file_content_tracker = FileContentTracker(lines)
|
340
442
|
format_file_content(file_content_tracker, parsed_arguments)
|
341
443
|
is_changed = file_content_tracker.is_changed()
|
342
444
|
if parsed_arguments.verbose:
|
@@ -348,9 +450,11 @@ def reformat_file(file_name: str, parsed_arguments: argparse.Namespace) -> bool:
|
|
348
450
|
f"[RED]needs to be formatted[RESET_ALL]",
|
349
451
|
parsed_arguments,
|
350
452
|
)
|
351
|
-
for
|
453
|
+
for line_change in file_content_tracker.line_changes:
|
352
454
|
color_print(
|
353
|
-
f" [BOLD][BLUE]↳
|
455
|
+
f" [BOLD][BLUE]↳ line {line_change.line_number + 1}: "
|
456
|
+
f"[WHITE]{line_change.check_only}[RESET_ALL]",
|
457
|
+
parsed_arguments,
|
354
458
|
)
|
355
459
|
else:
|
356
460
|
if parsed_arguments.verbose:
|
@@ -362,9 +466,15 @@ def reformat_file(file_name: str, parsed_arguments: argparse.Namespace) -> bool:
|
|
362
466
|
else:
|
363
467
|
if is_changed:
|
364
468
|
color_print(f"[WHITE]Reformatted [BOLD]{file_name}[RESET_ALL]", parsed_arguments)
|
365
|
-
for
|
366
|
-
color_print(
|
367
|
-
|
469
|
+
for line_change in file_content_tracker.line_changes:
|
470
|
+
color_print(
|
471
|
+
f" [BOLD][BLUE]↳ line {line_change.line_number + 1}: "
|
472
|
+
f"[WHITE]{line_change.change}[RESET_ALL]",
|
473
|
+
parsed_arguments,
|
474
|
+
)
|
475
|
+
write_file(
|
476
|
+
file_name, concatenate_lines(file_content_tracker.lines), parsed_arguments.encoding
|
477
|
+
)
|
368
478
|
else:
|
369
479
|
if parsed_arguments.verbose:
|
370
480
|
color_print(f"[WHITE]{file_name} [BLUE]left unchanged[RESET_ALL]", parsed_arguments)
|
whitespace_format-0.0.3/setup.py
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
from setuptools import setup
|
3
|
-
|
4
|
-
modules = \
|
5
|
-
['whitespace_format']
|
6
|
-
entry_points = \
|
7
|
-
{'console_scripts': ['whitespace-format = whitespace_format:main']}
|
8
|
-
|
9
|
-
setup_kwargs = {
|
10
|
-
'name': 'whitespace-format',
|
11
|
-
'version': '0.0.3',
|
12
|
-
'description': 'Linter and formatter for source code files and text files',
|
13
|
-
'long_description': '# whitespace-format\n\n[](https://dl.circleci.com/status-badge/redirect/gh/DavidPal/whitespace-format/tree/main)\n\n\n\nLinter and formatter for source code files and text files.\n\nThe purpose of this tool is to normalize source code files (e.g. Python, Java,\nC/C++, Ruby, Go, JavaScript, etc.) and text files (HTML, JSON, YAML, CSV,\nMarkDown, LaTeX) before checking them into a version control system.\n\nThe features include:\n\n* Auto-detection of new line markers (Linux `\\n`, Windows `\\r\\r`, Mac `\\r`).\n* Add a new line marker at the end of the file if it is missing.\n* Make new line markers consistent.\n* Remove empty lines at the end of the file.\n* Remove whitespace at the end of each line.\n* Replace tabs with spaces.\n* Remove/replace non-standard whitespace characters.\n\nThe formatting changes are\n[idempotent](https://en.wikipedia.org/wiki/Idempotence), i.e., running the tool\nsecond time (with the same parameters) has no effect.\n\n## Installation\n\n```shell\npip install whitespace-format\n```\n\nInstallation requires Python 3.7.5 or higher.\n\n## Usage\n\nA sample command that formats source code files:\n```shell\nwhitespace-format \\\n --exclude ".git/|.idea/|.pyc$" \\\n --new-line-marker linux \\\n --normalize-new-line-markers \\\n foo.txt my_project/\n```\nThe command above formats `foo.txt` and all files contained `my_project/` and\nits subdirectories. Files that contain `.git/` or `.idea/` in their (relative)\npath are excluded. For example, files in `my_project/.git/` and files in\n`my_project/.idea/` are excluded. Likewise, files ending with `*.pyc` are\nexcluded.\n\nIf you want only know if any changes **would be** made, add `--check-only` option:\n```shell\nwhitespace-format \\\n --exclude ".git/|.idea/|.pyc$" \\\n --check-only \\\n --new-line-marker linux \\\n --normalize-new-line-markers \\\n foo.txt my_project/\n```\nThis command can be used as a validation step before checking the source files\ninto a version control system. The command outputs non-zero exit code if any\nof the files would be formatted.\n\n### Options\n\n* `--check-only` -- Do not format files. Only report which files would be formatted.\n* `--follow-symlinks` -- Follow symbolic links when searching for files.\n* `--exclude=REGEX` -- Regular expression that specifies which files to exclude.\nThe regular expression is evaluated on the path of each file.\n* `--verbose` -- Print more messages than normally.\n* `--quiet` -- Do not print any messages, except for errors when reading or writing files.\n\n### Formatting options\n\n* `--add-new-line-marker-at-end-of-file` -- Add missing new line marker at end of each file.\n* `--remove-new-line-marker-from-end-of-file` -- Remove all new line marker(s) from the end of each file.\nThis option is ignored when `--add-new-line-marker-at-end-of-file` is used.\nEmpty lines at the end of the file are removed.\n* `--normalize-new-line-markers` -- Make new line markers consistent in each file\nby replacing `\\\\r\\\\n`, `\\\\n`, and `\\r` with a consistent new line marker.\n* `--remove-trailing-whitespace` -- Remove whitespace at the end of each line.\n* `--remove-trailing-empty-lines` -- Remove empty lines at the end of each file.\n* `--new-line-marker=MARKER` -- This option specifies what new line marker to use.\n`MARKER` must be one of the following:\n * `auto` -- Use new line marker that is the most common in each individual file.\n If no new line marker is present in the file, Linux `\\n` is used.\n This is the default option.\n * `linux` -- Use Linux new line marker `\\\\n`.\n * `mac` -- Use Mac new line marker `\\\\r`.\n * `windows` -- Use Windows new line marker `\\\\r\\\\n`.\n* `--encoding` -- Text encoding for both reading and writing files. Default encoding is `utf-8`.\nList of supported encodings can be found at\nhttps://docs.python.org/3/library/codecs.html#standard-encodings\n\nNote that input files can contain an arbitrary mix of new line markers `\\n`,\n`\\r`, `\\r\\n` even within the same file. The option `--new-line-marker`\nspecifies the character that should be in the formatted file.\n\nAn opinionated combination of options is:\n```shell\nwhitespace-format \\\n --new-line-marker=linux \\\n --add-new-line-marker-at-end-of-file \\\n --normalize-new-line-markers \\\n --remove-trailing-whitespace \\\n --remove-trailing-empty-lines \\\n foo.txt my_project/\n```\nThis should work well for common programming languages (e.g. Python, Java,\nC/C++, JavaScript) and common text file formats (e.g. CSV, LaTeX, JSON, YAML,\nHTML, MarkDown).\n\n### Empty files\n\nThere are separate options for handling empty files and files consisting of\nwhitespace characters only:\n\n* `--normalize-empty-files=MODE`\n* `--normalize-whitespace-only-files=MODE`\n\nwhere `MODE` is one of the following:\n\n* `ignore` -- Leave the file as is. This is the default option.\n* `empty` -- Replace the file with an empty file.\n* `one-line` -- Replace each file with a file consisting of a single new line marker.\n\nDepending on the mode, an empty file or a whitespace-only file will be either\nignored, replaced by a zero-byte file, or replaced by a file consisting of\nsingle end of line marker.\n\nIf `--normalize-whitespace-only-files` is set to `empty`,\n`--normalize-empty-files setting` set to `empty` as well. In other words,\ncombination `--normalize-whitespace-only-files=empty` and\n`--normalize-empty-files=one-line` is not allowed, since it would lead to\nbehavior that is not idempotent.\n\n### Special characters\n\n* `--replace-tabs-with-spaces=N` -- Replace tabs with spaces.\nWhere is `N` is the number of spaces. If `N` is negative, tabs are not replaced.\nDefault value is `-1`.\n\n* `--normalize-non-standard-whitespace=MODE` -- Replace or remove\nnon-standard whitespace characters (`\\v` and `\\f`). `MODE` must be one of the following:\n * `ignore` -- Leave `\\v` and `f` as is. This is the default option.\n * `replace` -- Replace any occurrence of `\\v` or `\\f` with a single space.\n * `remove` -- Remove all occurrences of `\\v` and `\\f`\n\n## License\n\nMIT\n\n## MacOS development setup\n\n1) Make sure you have [brew](https://brew.sh/) package manager installed.\n\n2) Install [pyenv](https://github.com/pyenv/pyenv), [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)\n and [poetry](https://python-poetry.org/):\n ```shell\n brew install pyenv\n brew install pyenv-virtualenv\n brew install poetry\n ```\n\n3) Create Python virtual environment with the correct Python version:\n ```shell\n make install-python\n make create-environment\n ```\n\n4) Add the following lines to `.zshrc` or `.bash_profile` and restart the terminal:\n ```shell\n # Pyenv settings\n export PYENV_ROOT="$HOME/.pyenv"\n export PATH="$PYENV_ROOT/bin:$PATH"\n eval "$(pyenv init --path)"\n eval "$(pyenv virtualenv-init -)"\n ```\n\n5) Install all dependencies\n ```shell\n make install-dependecies\n ```\n\nIf you need to delete the Python virtual environment, you can do so with the\ncommand `make delete-environment`.\n\n## Running unit tests and code checks\n\nIf you make code change, run unit tests and code checks with the command:\n```shell\nmake clean whitespace-format-check isort-check black-check flake8 pydocstyle pylint mypy test coverage\n```\n\nEach make target runs different checks:\n- `clean` deletes temporary files\n- `whitespace-format-check` runs [whitespace-format](https://github.com/DavidPal/whitespace-format) checker on all files\n- `isort-check` runs [isort](https://pycqa.github.io/isort/) checker of imports in `*.py` files\n- `black-check` runs [black](https://github.com/psf/black/) code format checker on `*.py` files\n- `flake8` runs [flake8](https://flake8.pycqa.org/) code style checker on `*.py` files\n- `pydocstyle` runs [pydocstyle](http://www.pydocstyle.org/) docstring checker on `*.py` files\n- `pylint` runs [pylint](https://pylint.org/) code checker on `*.py` files\n- `mypy` runs [mypy](http://mypy-lang.org/) type checker on `*.py` files\n- `test` runs unit tests\n- `coverage` generates code coverage report\n\nYou can automatically format code with the command:\n```shell\nmake isort-format black-format whitespace-format\n```\n\n## Modifying dependencies\n\nThe list of Python packages that this project depends on is specified in\n`pyproject.toml` and in `poetry.lock` files. The file `pyproject.toml` can be\nedited by humans. The file `poetry.lock` is automatically generated by\n`poetry`.\n\nInstall a development dependency with the command:\n```shell\npoetry add --dev <some_new_python_tool>\n```\n\nInstall a new production dependency with the command:\n```shell\npoetry add <some_python_library>\n```\n\n### Manual modification of `pyproject.toml`\n\nInstead of using `poetry add` command, you can edit `pyproject.toml` file. Then,\nregenerate `poetry.lock` file with the command:\n```shell\npoetry lock\n```\nor the command:\n```shell\npoetry lock --no-update\n```\nThe latter command does not update already locked packages.\n\n### Fixing broken Python environment\n\nIf your Python virtual environment becomes broken or polluted with unnecessary\npackages, delete it, recreate it from scratch and install dependencies a fresh\nwith the following commands:\n```shell\nmake delete-environment\nmake create-environment\nmake install-dependencies\n```\n',
|
14
|
-
'author': 'David Pal',
|
15
|
-
'author_email': 'davidko.pal@gmail.com',
|
16
|
-
'maintainer': 'None',
|
17
|
-
'maintainer_email': 'None',
|
18
|
-
'url': 'https://github.com/DavidPal/whitespace-format',
|
19
|
-
'py_modules': modules,
|
20
|
-
'entry_points': entry_points,
|
21
|
-
'python_requires': '>=3.7.2,<4.0.0',
|
22
|
-
}
|
23
|
-
|
24
|
-
|
25
|
-
setup(**setup_kwargs)
|
File without changes
|