minimindslab-csv-headers-align 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.
@@ -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,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: minimindslab-csv-headers-align
3
+ Version: 0.1.0
4
+ Summary: Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns.
5
+ Author: MiniMindsLab
6
+ License: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
12
+ # MiniMindsLab CSV Headers Align
13
+
14
+ Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install minimindslab-csv-headers-align
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```python
25
+ from minimindslab_csv_headers_align import align_headers
26
+
27
+ header = ["id", "name", "email", "legacy"]
28
+ target = ["name", "email", "id", "country"]
29
+
30
+ result = align_headers(header, target)
31
+
32
+ print(result.aligned) # ['name', 'email', 'id']
33
+ print(result.missing) # ['country']
34
+ print(result.extra) # ['legacy']
35
+ ```
36
+
37
+ ## API
38
+
39
+ - `align_headers(header_row, target_headers, *, validate=False)`
40
+ - Returns `AlignmentResult(aligned, missing, extra)`.
41
+ - `aligned`: present columns in target order.
42
+ - `missing`: target headers not present in input.
43
+ - `extra`: input headers not present in target.
44
+ - If `validate=True`, raises `ValueError` when missing headers exist.
45
+
46
+ ## Notes
47
+
48
+ - Pure Python standard library only.
49
+ - Inputs are normalized to strings using `str(value)` for non-`None` values, and `""` for `None`.
50
+ - Duplicate values in `target_headers` are deduplicated by first appearance for deterministic behavior.
@@ -0,0 +1,39 @@
1
+ # MiniMindsLab CSV Headers Align
2
+
3
+ Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install minimindslab-csv-headers-align
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from minimindslab_csv_headers_align import align_headers
15
+
16
+ header = ["id", "name", "email", "legacy"]
17
+ target = ["name", "email", "id", "country"]
18
+
19
+ result = align_headers(header, target)
20
+
21
+ print(result.aligned) # ['name', 'email', 'id']
22
+ print(result.missing) # ['country']
23
+ print(result.extra) # ['legacy']
24
+ ```
25
+
26
+ ## API
27
+
28
+ - `align_headers(header_row, target_headers, *, validate=False)`
29
+ - Returns `AlignmentResult(aligned, missing, extra)`.
30
+ - `aligned`: present columns in target order.
31
+ - `missing`: target headers not present in input.
32
+ - `extra`: input headers not present in target.
33
+ - If `validate=True`, raises `ValueError` when missing headers exist.
34
+
35
+ ## Notes
36
+
37
+ - Pure Python standard library only.
38
+ - Inputs are normalized to strings using `str(value)` for non-`None` values, and `""` for `None`.
39
+ - Duplicate values in `target_headers` are deduplicated by first appearance for deterministic behavior.
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "minimindslab-csv-headers-align"
7
+ version = "0.1.0"
8
+ description = "Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "MiniMindsLab" }
14
+ ]
15
+ dependencies = []
16
+
17
+ [tool.setuptools]
18
+ package-dir = {"" = "src"}
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,80 @@
1
+ """MiniMindsLab CSV Headers Align.
2
+
3
+ Utilities to align CSV header rows against a canonical target header order.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass
9
+ from typing import Iterable
10
+
11
+
12
+ @dataclass(frozen=True, slots=True)
13
+ class AlignmentResult:
14
+ """Result of header alignment.
15
+
16
+ Attributes:
17
+ aligned: Input columns that are present in target order.
18
+ missing: Target columns absent from the input.
19
+ extra: Input columns absent from target.
20
+ """
21
+
22
+ aligned: list[str]
23
+ missing: list[str]
24
+ extra: list[str]
25
+
26
+
27
+ def _normalize_value(value: object) -> str:
28
+ if value is None:
29
+ return ""
30
+ return str(value)
31
+
32
+
33
+ def _normalize_sequence(values: Iterable[object]) -> list[str]:
34
+ return [_normalize_value(v) for v in values]
35
+
36
+
37
+ def _dedupe_preserve_order(values: list[str]) -> list[str]:
38
+ seen: set[str] = set()
39
+ out: list[str] = []
40
+ for item in values:
41
+ if item not in seen:
42
+ seen.add(item)
43
+ out.append(item)
44
+ return out
45
+
46
+
47
+ def align_headers(
48
+ header_row: Iterable[object],
49
+ target_headers: Iterable[object],
50
+ *,
51
+ validate: bool = False,
52
+ ) -> AlignmentResult:
53
+ """Align an input header row to target header order.
54
+
55
+ Args:
56
+ header_row: Input header values.
57
+ target_headers: Canonical target sequence.
58
+ validate: If True, raise ValueError when missing target headers exist.
59
+
60
+ Returns:
61
+ AlignmentResult with aligned, missing, and extra columns.
62
+ """
63
+
64
+ header_list = _normalize_sequence(header_row)
65
+ target_list = _dedupe_preserve_order(_normalize_sequence(target_headers))
66
+
67
+ header_set = set(header_list)
68
+ target_set = set(target_list)
69
+
70
+ aligned = [col for col in target_list if col in header_set]
71
+ missing = [col for col in target_list if col not in header_set]
72
+ extra = [col for col in header_list if col not in target_set]
73
+
74
+ if validate and missing:
75
+ raise ValueError(f"Missing target columns: {missing}")
76
+
77
+ return AlignmentResult(aligned=aligned, missing=missing, extra=extra)
78
+
79
+
80
+ __all__ = ["AlignmentResult", "align_headers"]
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: minimindslab-csv-headers-align
3
+ Version: 0.1.0
4
+ Summary: Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns.
5
+ Author: MiniMindsLab
6
+ License: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
12
+ # MiniMindsLab CSV Headers Align
13
+
14
+ Normalize CSV header order to match a target header list, reordering present columns and optionally identifying missing or extra columns.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install minimindslab-csv-headers-align
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```python
25
+ from minimindslab_csv_headers_align import align_headers
26
+
27
+ header = ["id", "name", "email", "legacy"]
28
+ target = ["name", "email", "id", "country"]
29
+
30
+ result = align_headers(header, target)
31
+
32
+ print(result.aligned) # ['name', 'email', 'id']
33
+ print(result.missing) # ['country']
34
+ print(result.extra) # ['legacy']
35
+ ```
36
+
37
+ ## API
38
+
39
+ - `align_headers(header_row, target_headers, *, validate=False)`
40
+ - Returns `AlignmentResult(aligned, missing, extra)`.
41
+ - `aligned`: present columns in target order.
42
+ - `missing`: target headers not present in input.
43
+ - `extra`: input headers not present in target.
44
+ - If `validate=True`, raises `ValueError` when missing headers exist.
45
+
46
+ ## Notes
47
+
48
+ - Pure Python standard library only.
49
+ - Inputs are normalized to strings using `str(value)` for non-`None` values, and `""` for `None`.
50
+ - Duplicate values in `target_headers` are deduplicated by first appearance for deterministic behavior.
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/minimindslab_csv_headers_align/__init__.py
5
+ src/minimindslab_csv_headers_align.egg-info/PKG-INFO
6
+ src/minimindslab_csv_headers_align.egg-info/SOURCES.txt
7
+ src/minimindslab_csv_headers_align.egg-info/dependency_links.txt
8
+ src/minimindslab_csv_headers_align.egg-info/top_level.txt
9
+ tests/test_headers_align.py
@@ -0,0 +1,49 @@
1
+ import unittest
2
+
3
+ from minimindslab_csv_headers_align import AlignmentResult, align_headers
4
+
5
+
6
+ class TestHeadersAlign(unittest.TestCase):
7
+ def test_acceptance_reorders_present_columns_in_target_order(self):
8
+ header = ["id", "name", "email", "legacy"]
9
+ target = ["name", "email", "id", "country"]
10
+ result = align_headers(header, target)
11
+ self.assertEqual(result.aligned, ["name", "email", "id"])
12
+
13
+ def test_acceptance_missing_reported_without_raise_when_validate_false(self):
14
+ header = ["a", "b"]
15
+ target = ["a", "b", "c", "d"]
16
+ result = align_headers(header, target, validate=False)
17
+ self.assertEqual(result.missing, ["c", "d"])
18
+
19
+ def test_acceptance_extra_reported_and_separate(self):
20
+ header = ["x", "a", "b", "z"]
21
+ target = ["a", "b", "c"]
22
+ result = align_headers(header, target)
23
+ self.assertEqual(result.aligned, ["a", "b"])
24
+ self.assertEqual(result.extra, ["x", "z"])
25
+
26
+ def test_acceptance_non_string_boolean_none_inputs_predictable(self):
27
+ header = [True, None, 5, "x"]
28
+ target = ["", "True", "x", "7"]
29
+ result = align_headers(header, target)
30
+ self.assertEqual(result.aligned, ["", "True", "x"])
31
+ self.assertEqual(result.missing, ["7"])
32
+ self.assertEqual(result.extra, ["5"])
33
+
34
+ def test_negative_validate_true_raises_on_missing(self):
35
+ with self.assertRaises(ValueError):
36
+ align_headers(["a"], ["a", "b"], validate=True)
37
+
38
+ def test_target_deduplicated_deterministically(self):
39
+ result = align_headers(["a", "b"], ["a", "a", "b", "a"])
40
+ self.assertEqual(result.aligned, ["a", "b"])
41
+ self.assertEqual(result.missing, [])
42
+
43
+ def test_returns_dataclass_result(self):
44
+ result = align_headers([], [])
45
+ self.assertIsInstance(result, AlignmentResult)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ unittest.main()