-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathMetadata_carbon_copy.py
150 lines (127 loc) · 4.5 KB
/
Metadata_carbon_copy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#! /usr/bin/env python3
# # -*- coding: utf-8 -*-
"""
Metadata Carbon Copy tool
Makes copies of the source metadata file soil_metadata_<SSA>.xml
and writes a new copy to the respective SSURGO export directory
as a .met file.
It isn't an actual carbon copy as leading white space is stripped
and the following header line is added:
'<?xml version="1.0" encoding="ISO-8859-1"?>'
@author: Alexander Stum
@maintainer: Alexander Stum
@title: GIS Specialist & Soil Scientist
@organization: National Soil Survey Center, USDA-NRCS
@email: alexander.stum@usda.gov
@created 3/19/2025
@modified 4/03/2025
@by: Alexnder Stum
@version: 1.1
# ---
Update 1.1; 4/03/2025
- The script used incorrect regex logic to find export files
"""
import os
import re
import sys
import traceback
import arcpy
def pyErr(func: str) -> str:
"""When a python exception is raised, this funciton formats the traceback
message.
Parameters
----------
func : str
The function that raised the python error exception
Returns
-------
str
Formatted python error message
"""
try:
etype, exc, tb = sys.exc_info()
tbinfo = traceback.format_tb(tb)[0]
tbinfo = '\t\n'.join(tbinfo.split(','))
msgs = (f"PYTHON ERRORS:\nIn function: {func}"
f"\nTraceback info:\n{tbinfo}\nError Info:\n\t{exc}")
return msgs
except:
return "Error in pyErr method"
def arcpyErr(func: str) -> str:
"""When an arcpy by exception is raised, this function formats the
message returned by arcpy.
Parameters
----------
func : str
The function that raised the arcpy error exception
Returns
-------
str
Formatted arcpy error message
"""
try:
etype, exc, tb = sys.exc_info()
line = tb.tb_lineno
msgs = (f"ArcPy ERRORS:\nIn function: {func}\non line: {line}"
f"\n\t{arcpy.GetMessages(2)}\n")
return msgs
except:
return "Error in arcpyErr method"
def main():
try:
v = '1.1'
arcpy.AddMessage(f"Metadata Carbon Copy {v=}")
ssurgo_p = arcpy.GetParameterAsText(0)
export_p = arcpy.GetParameterAsText(1)
none_flag = None
hdr = '<?xml version="1.0" encoding="ISO-8859-1"?>'
source_dirs = [
d_n for d in os.scandir(ssurgo_p) if (
d.is_dir() and re.match(
r"[a-zA-Z]{2}[0-9]{3}",
d_n := d.name.removeprefix('soil_')
)
and os.path.exists(f"{d.path}/tabular")
and os.path.exists(f"{d.path}/spatial")
and os.path.exists(f"{d.path}/soil_metadata_{d_n.lower()}.xml")
)]
export_dirs = [
d.name for d in os.scandir(export_p) if (
d.is_dir() and re.match(r"[a-z]{2}[0-9]{3}", d.name)
and os.path.exists(f"{d.path}/{d.name}_a.shp")
and os.path.exists(f"{d.path}/{d.name}_b.shp")
)]
arcpy.AddMessage(f"{len(export_dirs)} export directories found")
strip = lambda l: l.lstrip() if l.lstrip() else '\n'
for ex_d in export_dirs:
ex_d = ex_d.upper()
if ex_d in source_dirs:
# read file
txt = f"{ssurgo_p}/{ex_d}/soil_metadata_{ex_d.lower()}.xml"
with open(txt, "r") as read_f:
txt_lines = read_f.readlines()
# remove leading whitespace
txt_lines = [strip(line) for line in txt_lines]
# write file
txt = f"{export_p}/{ex_d}/{ex_d.lower()}.met"
with open(txt, "w") as write_f:
write_f.write(hdr)
write_f.writelines(txt_lines)
arcpy.AddMessage(f"\tSuccessfully copied {txt}")
none_flag = 1
else:
arcpy.AddWarning(f"A source directory not found for {ex_d}")
if not none_flag:
arcpy.AddWarning(
"No valid export folders found and no metatdata files copied"
)
except arcpy.ExecuteError:
func = sys._getframe().f_code.co_name
arcpy.AddError(arcpyErr(func))
raise
except:
func = sys._getframe().f_code.co_name
arcpy.AddError(pyErr(func))
raise
if __name__ == '__main__':
main()