-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharcpy_extender_toolbox.pyt
177 lines (154 loc) · 6.75 KB
/
arcpy_extender_toolbox.pyt
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import os
import sys
import json
try:
import arcpy
except Exception:
raise ImportError('Could not find the arcpy module. Are you running this toolbox from ArcGIS?')
try:
import xgis
import xgis.log_utils as log
except ImportError:
from core import executor as xgis
from core import log_utils as log
logger = log.initialise_logger(to_file='xGISToolbox', force=True)
class Toolbox(object):
stored_parameters_file = os.path.join(os.path.expanduser("~"), 'xGISparameters.txt')
def __init__(self):
self.label = "xGIS"
self.alias = "Toolbox to perform an external execution"
# List of tool classes associated with this toolbox
self.tools = [Extender]
@classmethod
def store_parameters(self, parameters):
logger.info('Saving parameters')
stored_parameters = {}
for p in parameters:
if p.direction == "Output":
stored_parameters[p.name] = None
logger.info("Skipping {0}".format(p.name))
else:
stored_parameters[p.name] = p.valueAsText
logger.info(" {0}: {1}".format(p.name, p.valueAsText))
if stored_parameters != {}:
with open(self.stored_parameters_file, 'w+') as dump:
dump.write(json.dumps(stored_parameters))
@classmethod
def retrieve_parameters(self, parameters):
if not os.path.isfile(self.stored_parameters_file):
return parameters
else:
logger.info('Loading parameters')
with open(self.stored_parameters_file, 'r') as dump:
stored_parameters = json.loads(dump.read())
for p in parameters:
if p.name in stored_parameters:
logger.info(" {0}: {1}".format(p.name, stored_parameters[p.name]))
p.value = stored_parameters[p.name]
class Extender(object):
def __init__(self):
self.label = 'Extender'
self.description = 'Tool to perform an external execution'
self.canRunInBackground = True
def getParameterInfo(self):
# Define parameter definitions
parameters = []
params0 = arcpy.Parameter(
displayName='Script or executable to run externally',
name='exe',
datatype='DEFile',
parameterType='Required')
parameters.append(params0)
params1 = arcpy.Parameter(
displayName='Command line arguments',
name='args',
datatype='GPString',
parameterType='Optional')
parameters.append(params1)
params2 = arcpy.Parameter(
displayName='External libraries folder',
name='ext_libs',
datatype='DEWorkspace',
parameterType='Optional')
parameters.append(params2)
params3 = arcpy.Parameter(
displayName='Working directory',
name='wd',
datatype='DEWorkspace',
parameterType='Optional')
parameters.append(params3)
params4 = arcpy.Parameter(
displayName='Expected output path',
name='out_path',
datatype='GPString',
parameterType='Optional')
parameters.append(params4)
params5 = arcpy.Parameter(
displayName='out',
name='out',
datatype='DEFile',
parameterType='Derived',
direction='Output')
parameters.append(params5)
return parameters
def isLicensed(self): # optional
return True
def updateParameters(self, parameters): # optional
if parameters[0].value is None:
Toolbox.retrieve_parameters(parameters)
if all([p.hasBeenValidated for p in parameters]):
# Logic to make sure that we don't pass the previous output file to avoid layer locking (PB-14)
for p in parameters:
if p.direction == "Output":
p.value = None
Toolbox.store_parameters(parameters)
return
def updateMessages(self, parameters): # optional
if parameters[0].value and not parameters[0].hasBeenValidated:
if not os.access(parameters[0].valueAsText, os.X_OK):
parameters[0].setErrorMessage('The selected file is not an executable')
if parameters[1].value and not parameters[1].hasBeenValidated:
parameters[1].setWarningMessage('The following string will be split to {0}. Please check that this is what you expect. Argument grouping can be achieved using quotes or brackets'.format(self.split_args(parameters[1].valueAsText)))
if parameters[2].value and not parameters[2].hasBeenValidated:
if not os.path.isdir(parameters[2].valueAsText):
parameters[2].setErrorMessage('The selected path does not point to a valid directory')
if parameters[3].value and not parameters[3].hasBeenValidated:
if not os.path.isdir(parameters[3].valueAsText):
parameters[3].setErrorMessage('The selected path does not point to a valid directory')
return
def execute(self, parameters, messages):
exe = parameters[0].valueAsText
args = self.split_args(parameters[1].valueAsText) if parameters[1].value else []
ext_libs = parameters[2].valueAsText if parameters[2].value else False
wd = parameters[3].valueAsText if parameters[3].value else False
out = parameters[4].valueAsText if parameters[4].value else False
cmd_line = [exe] + args
try:
logger.info('Initialising external executor')
executor = xgis.Executor(cmd_line, external_libs=ext_libs, cwd=wd, logger=logger)
logger.info('Performing the calculation')
executor.run()
if out:
if not os.path.isfile(out):
raise RuntimeError('Could not find the expected output. Please check if the calculation completed successfully')
logger.info(self.__class__.__name__ + ' succesfully completed')
arcpy.SetParameter(len(parameters) - 1, out)
except Exception:
logger.exception(self.__class__.__name__ + ' failed with the following error')
sys.exit(1)
@staticmethod
def split_args(args_string):
args_string = str(args_string)
begin_i = 0
args = []
quote_flag = False
for i, c in enumerate(args_string):
if c == ' ' and not quote_flag:
if i - begin_i > 0:
args.append(args_string[begin_i:i])
begin_i = i + 1
elif c in ['"', "'", '(', ')', '[', ']', '{', '}']:
quote_flag = not quote_flag
if begin_i != len(args_string):
args.append(args_string[begin_i:])
return args