minimindslab-csv-normalize 0.1.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.
@@ -0,0 +1,6 @@
1
+ """MiniMindsLab CSV Normalize."""
2
+
3
+ from .core import normalize_csv
4
+
5
+ __all__ = ["normalize_csv"]
6
+ __version__ = "0.1.0"
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import sys
5
+
6
+ from .core import normalize_csv
7
+
8
+
9
+ def build_parser() -> argparse.ArgumentParser:
10
+ parser = argparse.ArgumentParser(description="Normalize small CSV text deterministically.")
11
+ parser.add_argument("--input", "-i", help="Path to input CSV file. If omitted, read from stdin.")
12
+ parser.add_argument("--no-sort-headers", action="store_true", help="Preserve original header order.")
13
+ parser.add_argument("--newline", choices=["lf", "crlf"], default="lf", help="Output newline style.")
14
+ return parser
15
+
16
+
17
+ def main() -> int:
18
+ parser = build_parser()
19
+ args = parser.parse_args()
20
+
21
+ if args.input:
22
+ with open(args.input, "r", encoding="utf-8", newline="") as f:
23
+ text = f.read()
24
+ else:
25
+ text = sys.stdin.read()
26
+
27
+ nl = "\n" if args.newline == "lf" else "\r\n"
28
+ result = normalize_csv(text, sort_headers=not args.no_sort_headers, newline=nl)
29
+ sys.stdout.write(result)
30
+ return 0
31
+
32
+
33
+ if __name__ == "__main__":
34
+ raise SystemExit(main())
@@ -0,0 +1,60 @@
1
+ """Core CSV normalization logic."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import csv
6
+ import io
7
+ from typing import List
8
+
9
+
10
+ def _normalize_newlines(text: str) -> str:
11
+ return text.replace("\r\n", "\n").replace("\r", "\n")
12
+
13
+
14
+ def normalize_csv(text: str, *, sort_headers: bool = True, newline: str = "\n") -> str:
15
+ """Normalize CSV text into stable output.
16
+
17
+ - Normalizes line endings in input.
18
+ - Trims leading/trailing whitespace for all cells.
19
+ - Optionally sorts headers alphabetically for deterministic column order.
20
+ - Emits output with a consistent newline and trailing newline when non-empty.
21
+ """
22
+ if not isinstance(text, str):
23
+ raise TypeError("text must be a str")
24
+ if newline not in {"\n", "\r\n"}:
25
+ raise ValueError("newline must be '\\n' or '\\r\\n'")
26
+
27
+ src = _normalize_newlines(text)
28
+ if src.strip() == "":
29
+ return ""
30
+
31
+ reader = csv.reader(io.StringIO(src))
32
+ rows: List[List[str]] = [[cell.strip() for cell in row] for row in reader]
33
+ if not rows:
34
+ return ""
35
+
36
+ header = rows[0]
37
+ data = rows[1:]
38
+
39
+ if sort_headers:
40
+ indices = sorted(range(len(header)), key=lambda i: (header[i], i))
41
+ header = [header[i] for i in indices]
42
+
43
+ def reorder(row: List[str]) -> List[str]:
44
+ padded = row + [""] * (len(indices) - len(row))
45
+ return [padded[i] if i < len(padded) else "" for i in indices]
46
+
47
+ data = [reorder(r) for r in data]
48
+ else:
49
+ data = [r + [""] * (len(header) - len(r)) if len(r) < len(header) else r[: len(header)] for r in data]
50
+
51
+ output = io.StringIO()
52
+ writer = csv.writer(output, lineterminator="\n")
53
+ writer.writerow(header)
54
+ for row in data:
55
+ writer.writerow(row)
56
+
57
+ rendered = output.getvalue()
58
+ if newline != "\n":
59
+ rendered = rendered.replace("\n", newline)
60
+ return rendered
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: minimindslab-csv-normalize
3
+ Version: 0.1.0
4
+ Summary: Normalize small CSV text into stable, comparison-friendly output with controllable header ordering, trimming, and line endings.
5
+ Author: MiniMindsLab
6
+ License: MIT
7
+ Keywords: csv,normalize,deterministic,cli
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Software Development :: Testing
15
+ Classifier: Topic :: Text Processing
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # MiniMindsLab CSV Normalize
22
+
23
+ Deterministically normalize small CSV text for stable diffs, tests, and reviews.
24
+
25
+ ## Features
26
+
27
+ - Trims surrounding whitespace in headers and cell values.
28
+ - Normalizes mixed line endings to `\n`.
29
+ - Optional stable header sorting.
30
+ - Deterministic output for identical logical input.
31
+ - Library API and CLI.
32
+
33
+ ## Library Usage
34
+
35
+ ```python
36
+ from minimindslab_csv_normalize import normalize_csv
37
+
38
+ raw = " Name , Age \r\n Alice , 30 \r\n"
39
+ out = normalize_csv(raw)
40
+ print(out)
41
+ # Age,Name\n30,Alice\n
42
+ # Keep original header order
43
+ out2 = normalize_csv(raw, sort_headers=False)
44
+ print(out2)
45
+ # Name,Age\nAlice,30\n
46
+ ```
47
+
48
+ ## CLI Usage
49
+
50
+ From stdin:
51
+
52
+ ```bash
53
+ echo " Name , Age \r\n Alice , 30 " | miniminds-csv-normalize
54
+ ```
55
+
56
+ From file:
57
+
58
+ ```bash
59
+ miniminds-csv-normalize --input sample.csv
60
+ ```
61
+
62
+ Disable header sorting:
63
+
64
+ ```bash
65
+ miniminds-csv-normalize --no-sort-headers --input sample.csv
66
+ ```
@@ -0,0 +1,9 @@
1
+ minimindslab_csv_normalize/__init__.py,sha256=NTaAKSAYJX86qDiTPiOhtodrql4AFiPfin4Pvnb23HM,118
2
+ minimindslab_csv_normalize/__main__.py,sha256=c43g7QNibxIQpGSUiQ37NovlNSyW-OJWNRZA9WcaBnA,1048
3
+ minimindslab_csv_normalize/core.py,sha256=XRDggK_dvAdZ9NSubZhSmzIRkScGYZD18Y05RI3DoAw,1862
4
+ minimindslab_csv_normalize-0.1.0.dist-info/licenses/LICENSE,sha256=9SsHAp-rmsco8evLbp-_802okWchTYdG-RZx5d3yddM,1069
5
+ minimindslab_csv_normalize-0.1.0.dist-info/METADATA,sha256=3FynG_S_bsa8CY_r77Uj-XISBQx6tANoVyNLI1tvXJI,1671
6
+ minimindslab_csv_normalize-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
7
+ minimindslab_csv_normalize-0.1.0.dist-info/entry_points.txt,sha256=9fmnYOanrvC7dY8vQvlPvbgR3evbNmsK3nZzl3mYlL0,85
8
+ minimindslab_csv_normalize-0.1.0.dist-info/top_level.txt,sha256=7ZG7hVBklhOY-TikYB-yne_tFjNPC4cutVSIVkHrZOg,27
9
+ minimindslab_csv_normalize-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ miniminds-csv-normalize = minimindslab_csv_normalize.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MiniMindsLab
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 @@
1
+ minimindslab_csv_normalize