ltc-code 0.2.11__tar.gz → 0.2.12__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.
- {ltc_code-0.2.11 → ltc_code-0.2.12}/PKG-INFO +1 -1
- {ltc_code-0.2.11 → ltc_code-0.2.12}/pyproject.toml +1 -1
- ltc_code-0.2.12/src/ltc_code/nsc/__init__.py +0 -0
- ltc_code-0.2.12/src/ltc_code/nsc/naics.csv +25 -0
- ltc_code-0.2.12/src/ltc_code/nsc/naics.py +126 -0
- ltc_code-0.2.12/src/ltc_code/nsc/naics_raw.xlsx +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/README.md +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/.DS_Store +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/aspire.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/check_cmo_apps.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/christel_house.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/democracy_prep.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/green_dot.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/helpers.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/ilt.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/kipp_nj.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/main.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/mappings.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/rocketship.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/yes_prep.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/aspire.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/christel_house.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/democracy_prep.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/green_dot.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/ilt.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/kipp.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/kipp_nj.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/rocketship.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/yes_prep.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/BALANCE.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/FS.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/ITT.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/TOT.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/apps_helpers.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/harmony.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260706_ceprscripts/main.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260712_uncommon_scripts/main.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260712_uncommon_scripts/mappings.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260712_uncommon_scripts/uncommon.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/__init__.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/aspire.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/check_cmo_apps.do +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/christel_house.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/green_dot.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/helpers.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/june13.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/june2.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/june30.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/june5.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/june7.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/kipp_nj.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/kipp_tx.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/main.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/mappings.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/may27.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/polars_dates.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/rocketship.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/schema_mapping.py +0 -0
- {ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/yes_prep.py +0 -0
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
naics_code,sector
|
|
2
|
+
11,"Agriculture, Forestry, Fishing and Hunting"
|
|
3
|
+
21,"Mining, Quarrying, and Oil and Gas Extraction"
|
|
4
|
+
22,Utilities
|
|
5
|
+
23,Construction
|
|
6
|
+
31,Manufacturing
|
|
7
|
+
32,Manufacturing
|
|
8
|
+
33,Manufacturing
|
|
9
|
+
42,Wholesale Trade
|
|
10
|
+
44,Retail Trade
|
|
11
|
+
45,Retail Trade
|
|
12
|
+
48,Transportation and Warehousing
|
|
13
|
+
49,Transportation and Warehousing
|
|
14
|
+
51,Information
|
|
15
|
+
52,Finance and Insurance
|
|
16
|
+
53,Real Estate and Rental and Leasing
|
|
17
|
+
54,"Professional, Scientific, and Technical Services"
|
|
18
|
+
55,Management of Companies and Enterprises
|
|
19
|
+
56,Administrative and Support and Waste Management and Remediation Services
|
|
20
|
+
61,Educational Services
|
|
21
|
+
62,Health Care and Social Assistance
|
|
22
|
+
71,"Arts, Entertainment, and Recreation"
|
|
23
|
+
72,Accommodation and Food Services
|
|
24
|
+
81,Other Services (except Public Administration)
|
|
25
|
+
92,Public Administration
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import csv
|
|
4
|
+
import re
|
|
5
|
+
import zipfile
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from xml.etree import ElementTree as ET
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
BASE_DIR = Path(__file__).resolve().parent
|
|
11
|
+
RAW_DIR = BASE_DIR
|
|
12
|
+
CLEAN_DIR = BASE_DIR
|
|
13
|
+
OUTPUT_PATH = BASE_DIR / "naics.csv"
|
|
14
|
+
|
|
15
|
+
NS = {"x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
|
|
16
|
+
SECTOR_CODE_RE = re.compile(r"^\s*(\d{2})(?:\s*-\s*(\d{2}))?\s*$")
|
|
17
|
+
LETTER_RE = re.compile(r"[A-Za-z]")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _shared_strings(workbook: zipfile.ZipFile) -> list[str]:
|
|
21
|
+
try:
|
|
22
|
+
root = ET.fromstring(workbook.read("xl/sharedStrings.xml"))
|
|
23
|
+
except KeyError:
|
|
24
|
+
return []
|
|
25
|
+
|
|
26
|
+
strings: list[str] = []
|
|
27
|
+
for item in root.findall("x:si", NS):
|
|
28
|
+
strings.append("".join(text.text or "" for text in item.findall(".//x:t", NS)))
|
|
29
|
+
return strings
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _cell_value(cell: ET.Element, shared_strings: list[str]) -> str:
|
|
33
|
+
cell_type = cell.attrib.get("t")
|
|
34
|
+
|
|
35
|
+
if cell_type == "inlineStr":
|
|
36
|
+
return "".join(text.text or "" for text in cell.findall(".//x:t", NS)).strip()
|
|
37
|
+
|
|
38
|
+
value = cell.find("x:v", NS)
|
|
39
|
+
if value is None or value.text is None:
|
|
40
|
+
return ""
|
|
41
|
+
|
|
42
|
+
text = value.text.strip()
|
|
43
|
+
if cell_type == "s":
|
|
44
|
+
return shared_strings[int(text)].strip()
|
|
45
|
+
return text
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def read_first_sheet_rows(path: Path) -> list[list[str]]:
|
|
49
|
+
with zipfile.ZipFile(path) as workbook:
|
|
50
|
+
shared_strings = _shared_strings(workbook)
|
|
51
|
+
sheet = ET.fromstring(workbook.read("xl/worksheets/sheet1.xml"))
|
|
52
|
+
|
|
53
|
+
rows: list[list[str]] = []
|
|
54
|
+
for row in sheet.findall(".//x:sheetData/x:row", NS):
|
|
55
|
+
values = [
|
|
56
|
+
_cell_value(cell, shared_strings)
|
|
57
|
+
for cell in row.findall("x:c", NS)
|
|
58
|
+
]
|
|
59
|
+
rows.append(values)
|
|
60
|
+
return rows
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def expand_sector_code(code: str) -> list[str]:
|
|
64
|
+
match = SECTOR_CODE_RE.fullmatch(code)
|
|
65
|
+
if match is None:
|
|
66
|
+
return []
|
|
67
|
+
|
|
68
|
+
start = int(match.group(1))
|
|
69
|
+
end = int(match.group(2) or match.group(1))
|
|
70
|
+
return [f"{sector:02d}" for sector in range(start, end + 1)]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def clean_naics_rows(rows: list[list[str]]) -> list[dict[str, str]]:
|
|
74
|
+
cleaned: list[dict[str, str]] = []
|
|
75
|
+
seen: set[tuple[str, str]] = set()
|
|
76
|
+
|
|
77
|
+
for row in rows:
|
|
78
|
+
values = [value.strip() for value in row if value.strip()]
|
|
79
|
+
if len(values) < 2:
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
for index, value in enumerate(values[:-1]):
|
|
83
|
+
sector_codes = expand_sector_code(value)
|
|
84
|
+
if not sector_codes:
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
sector_name = values[index + 1].strip()
|
|
88
|
+
if (
|
|
89
|
+
not sector_name
|
|
90
|
+
or not LETTER_RE.search(sector_name)
|
|
91
|
+
or sector_name.lower() in {"sector", "title", "description"}
|
|
92
|
+
):
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
for sector_code in sector_codes:
|
|
96
|
+
record = (sector_code, sector_name)
|
|
97
|
+
if record in seen:
|
|
98
|
+
continue
|
|
99
|
+
cleaned.append({"naics_code": sector_code, "sector": sector_name})
|
|
100
|
+
seen.add(record)
|
|
101
|
+
break
|
|
102
|
+
|
|
103
|
+
return cleaned
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main() -> None:
|
|
107
|
+
source_files = sorted(RAW_DIR.glob("*.xlsx"))
|
|
108
|
+
if not source_files:
|
|
109
|
+
raise FileNotFoundError(f"No .xlsx files found in {RAW_DIR}")
|
|
110
|
+
|
|
111
|
+
rows = read_first_sheet_rows(source_files[0])
|
|
112
|
+
cleaned = clean_naics_rows(rows)
|
|
113
|
+
if not cleaned:
|
|
114
|
+
raise ValueError(f"No sector-level NAICS rows found in {source_files[0]}")
|
|
115
|
+
|
|
116
|
+
CLEAN_DIR.mkdir(parents=True, exist_ok=True)
|
|
117
|
+
with OUTPUT_PATH.open("w", newline="", encoding="utf-8") as output_file:
|
|
118
|
+
writer = csv.DictWriter(output_file, fieldnames=["naics_code", "sector"])
|
|
119
|
+
writer.writeheader()
|
|
120
|
+
writer.writerows(cleaned)
|
|
121
|
+
|
|
122
|
+
print(f"Wrote {len(cleaned)} rows to {OUTPUT_PATH}")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
main()
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/aspire.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/check_cmo_apps.do
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/christel_house.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/democracy_prep.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/green_dot.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/kipp_nj.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/mappings.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/rocketship.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260614_new_build_scripts_update/yes_prep.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/christel_house.py
RENAMED
|
File without changes
|
{ltc_code-0.2.11 → ltc_code-0.2.12}/src/ltc_code/20260630_census_disclosure/democracy_prep.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|