Subject: Marine Geospatial Ecology Tools (MGET) help
Text archives
From: | "Jason Roberts" <> |
---|---|
To: | <>, <> |
Subject: | RE: ArcGISRasterSamplerSampleRasters |
Date: | Thu, 11 Dec 2008 21:41:03 -0500 |
Hi Joe,
Thanks for your interest in MGET. I'm sorry the sampling tool is not working
for you. The short answer is that the tool does not currently support
sampling raster bands, only rasters or raster layers. But I have a solution
for you.
First, here is some code that demonstrates how to sample rasters that do not
have bands from a traditional Python geoprocessing script:
# Instantiate Arc 9.2 geoprocessor.
import arcgisscripting
gp = arcgisscripting.create()
# Reference MGET toolbox. Note: path may change before MGET 0.7 is
# released. See https://code.env.duke.edu/projects/mget/ticket/299
gp.AddToolbox(r'C:\Python24\Lib\site-packages\GeoEco\ArcGISToolbox\Marine
Geospatial Ecology Tools.tbx')
# A simple sampling example for two fields:
points = r'C:\HabModExample2\Geodatabase.mdb\PointsToSample'
rasters = r'C:\HabModExample2\OceanographyRasters\Chl\Monthly\chl199908;' + \
r'C:\HabModExample2\OceanographyRasters\SST\Monthly\sst\sst199908'
fields = 'Chlorophyll;SST'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
# Since we are sampling Chl and SST for August 1998, we can restrict
# the sampler to just do the points that have that date. Since we're
# querying an MS Access database, we can use VBScript DatePart
# function. This is not very efficient, but will work.
where = 'DatePart("m", [obs_date]) = 8'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields, where)
# If the destination field has the an integer data type (i.e. SHORT or
# LONG), we must explicitly cast the sampled values to integers. This
# is because the MGET tool always gets floats back from ArcGIS, even
# when sampling integer rasters. A future version of the MGET tool
# will do this automatically, or call ArcGIS in a different way, so
# this is not required. Sorry for the inconvenience.
fields = 'Bathymetry'
rasters = r'C:\HabModExample2\OceanographyRasters\Bathymetry\etopo2v2'
expressions = 'int(value)' # etopo2v2 is depth as integer
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields, where,
'#', '#', expressions)
I saved that script to C:\SampTest\SampTest.py. It uses points and rasters
from the HabModExample2 habitat modeling example on the MGET web site. I ran
it on an Arc 9.2 SP6 machine and got the following output. You'll see the
output if you run it from a CMD shell, but if you run it from a Python
debugger (e.g. PythonWin) I don’t think you'll see it because those debuggers
do not traditionally capture messages written to the stdout stream.
C:\SampTest>SampTest.py
2008-12-11 21:03:29,246 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Chl\\Monthly\\chl199908',
u'C:\\HabModExample2\\OceanographyRasters\\SST\\Monthly\\sst\\sst199908'],
fields=[u'Chlorophyll', u'SST']...
2008-12-11 21:03:47,763 INFO Sampled 2 rasters at 600 points.
2008-12-11 21:04:06,226 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Chl\\Monthly\\chl199908',
u'C:\\HabModExample2\\OceanographyRasters\\SST\\Monthly\\sst\\sst199908'],
fields=[u'Chlorophyll', u'SST'], where=DatePart("m", [obs_date]) = 8...
2008-12-11 21:04:23,822 INFO Sampled 2 rasters at 328 points.
2008-12-11 21:04:40,775 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Bathymetry\\etopo2v2'],
fields=[u'Bathymetry'], where=DatePart("m", [obs_date]) = 8...
2008-12-11 21:04:58,901 INFO Sampled 1 rasters at 328 points.
Here is what code for sampling bands should look like:
# Create a raster with two bands so we can test band sampling.
bands = r'C:\HabModExample2\OceanographyRasters\Chl\Monthly\chl199908;' + \
r'C:\HabModExample2\OceanographyRasters\SST\Monthly\sst\sst199908'
gp.OverwriteOutput = True
gp.CompositeBands_management(bands, r'C:\SampTest\multiband.img')
# Sample the bands.
rasters = r'C:\SampTest\multiband.img\Band_1;' + \
r'C:\SampTest\multiband.img\Band_2'
fields = 'Chlorophyll;SST'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
But the tool fails with this message:
C:\SampTest>SampTest.py
2008-12-11 21:13:36,144 ERROR ValueError: The value specified for the element
0 of the rasters parameter (where 0 is the first element),
C:\SampTest\multiband.img\Band_1, exists but it is not a raster or raster
layer. Please specify a raster or raster layer.
Traceback (most recent call last):
File "C:\SampTest\SampTest.py", line 56, in ?
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
RuntimeError:
ValueError: The value specified for the element 0 of the rasters parameter
(where 0 is the first element), C:\SampTest\multiband.img\Band_1, exists but
it is not a raster or raster layer. Please specify a raster or raster layer.
Error in script ArcGISRasterSamplerSampleRasters.
Error in executing: cmd.exe /C
C:\Python24\Lib\SITE-P~1\GeoEco\ARCGIS~1\Scripts\AR87D7~1.PY
"C:\HabModExample2\Geodatabase.mdb\PointsToSample"
"C:\SampTest\multiband.img\Band_1;C:\SampTest\multiband.img\Band_2"
"Chlorophyll;SST" "#" "NEAREST" "#" "#" "#"
"C:\HabModExample2\Geodatabase.mdb\PointsToSample"
Failed to execute (ArcGISRasterSamplerSampleRasters).
If you are not seeing anything like that, then there is some other problem.
If you're trying to run it from PythonWin, IDLE, or another editor, try it
from a CMD shell instead. If you still don't see any messages, it probably
means there is an installation problem. Usually it means the pywin32 Python
package is not installed. You could check for that (see MGET's Installation
Instructions).
Now, assuming you can reproduce an error that looks like the above (i.e.
"ValueError: The value specified ... exists but it is not a raster or raster
layer.") you can fix it by overwriting your file
C:\Python24\Lib\site-packages\GeoEco\Types.py with the one attached to this
message. This contains a one line fix that enables the tool to sample bands.
My apologies for the bug. You should then get this output:
C:\SampTest>SampTest.py
2008-12-11 21:18:13,516 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\SampTest\\multiband.img\\Band_1',
u'C:\\SampTest\\multiband.img\\Band_2'], fields=[u'Chlorophyll', u'SST']...
2008-12-11 21:18:35,184 INFO Sampled 2 rasters at 600 points.
Hope that helps. Let me know if it does not...
Jason
-----Original Message-----
From:
[mailto:]
Sent: Thursday, December 11, 2008 7:55 PM
To:
Subject: ArcGISRasterSamplerSampleRasters
Hi MGET-ers.
I'm new to the list and new to the GeoEco toolbox, so here goes...
I'm trying to sample all the rasters (including multiple raster bands) in a
directory using the ArcGISRasterSamplerSampleRasters tool. All the rasters are
Erdas IMAGEs (.img), 7 are single-band, 3 are 3-band, and 3 are 6-band images,
for a total of 34 fields being added to my point shapefile.
I originally downloaded the toolbox because I had previously tried Python to
use the "Sample" command and also to loop through "Extract Values to Points",
but ran into errors in both. (The former would not allow that many rasters to
be sampled, and the latter just failed at various places, giving the "ERROR
99999: unknown error" message.)
So, can the ArcGISRasterSamplerSampleRasters tool sample all bands of
multi-band rasters, or do I need to copy each band as a single-band raster?
I'm
running the tool unsuccessfully in a Python script now, but I get no error
messages when it fails, so I'm guessing that this is the problem. Here's the
pseudocode of what I'm doing:
rasters = 'raster1.img;raster2.img\Band_1;raster2.img\Band_2...'
fields = 'raster1;raster2_1;raster2_2...'
gp.ArcGISRasterSamplerSampleRasters(shapefile, rasters, fields)
Thanks,
Joe
# Types.py - Provides classes derived from GeoEco.Metadata.TypeMetadata that
# represent data types of properties and method arguments and return values
for
# classes in the GeoEco Python package.
#
# Copyright (C) 2007 Jason J. Roberts
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License (available in the file LICENSE.TXT)
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
import datetime
import inspect
import operator
import os.path
import re
import sys
import time
import types
import xml.dom
from GeoEco.DynamicDocString import DynamicDocString
from GeoEco.Internationalization import _
from GeoEco.Metadata import Metadata, TypeMetadata
# Private helper function for raising exceptions
def _RaiseException(e):
from GeoEco.Logging import Logger
Logger.RaiseException(e)
# Types representing Python class instances or classes
class AnyObjectTypeMetadata(TypeMetadata):
def __init__(self, canBeNone=False):
super(AnyObjectTypeMetadata,
self).__init__(pythonType=types.ObjectType,
canBeNone=canBeNone,
comIDLType=u'VARIANT',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class NoneTypeMetadata(TypeMetadata):
def __init__(self):
super(NoneTypeMetadata, self).__init__(pythonType=types.NoneType,
canBeNone=True)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is not None:
_RaiseException(TypeError(_(u'The %s must be None (also called
null or empty in languages other than Python).') % variableName))
return (False, value)
class ClassTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassTypeMetadata, self).__init__(pythonType=cls,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is None:
if not self.CanBeNone:
_RaiseException(TypeError(_(u'The %s is required. Please
provide a value.') % variableName))
elif not issubclass(value, self.PythonType):
_RaiseException(TypeError(_(u'The value provided for the
%(variable)s is invalid because it is a %(type)s, an invalid type. Please
provide the class %(class)s or a subclass.') % {u'variable' : variableName,
u'type' : type(value).__name__, u'class' : self.PythonType.__name__}))
return (False, value)
class ClassInstanceTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassInstanceTypeMetadata, self).__init__(pythonType=cls,
canBeNone=canBeNone)
class ClassOrClassInstanceTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassOrClassInstanceTypeMetadata,
self).__init__(pythonType=cls, canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is None:
if not self.CanBeNone:
_RaiseException(TypeError(_(u'The %s is required. Please
provide a value.') % variableName))
elif not (inspect.isclass(value) and issubclass(value,
self.PythonType)) and not isinstance(value, self.PythonType):
_RaiseException(TypeError(_(u'The value provided for the
%(variable)s is invalid because it is a %(type)s, an invalid type. Please
provide the class %(class)s, a subclass, or an instance of it or a
subclass.') % {u'variable' : variableName, u'type' : type(value).__name__,
u'class' : self.PythonType.__name__}))
return (False, value)
# Simple Python types from which many other types derive
class BooleanTypeMetadata(TypeMetadata):
def __init__(self,
canBeNone=False,
allowedValues=None):
super(BooleanTypeMetadata,
self).__init__(pythonType=types.BooleanType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'VARIANT_BOOL',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPBooleanTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'boolean')).appendChild(document.createTextNode(unicode(value).lower()))
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.BooleanType), u'value must be a
boolean'
if value:
return '-1' # VARIANT_TRUE
return '0' # VARIANT_FALSE
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(BooleanTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip().lower()
if s == u'true':
return True
if s == u'false':
return False
_RaiseException(ValueError(_(u'Failed to parse a boolean from the
string "%(string)s" provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). Please provide either "True" or "False".') %
{u'string' : s, u'paramName' : paramDisplayName, u'paramIndex' : paramIndex}))
class DateTimeTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (datetime.datetime, types.NoneType)),
u'minValue must be a datetime.datetime, or None'
assert isinstance(maxValue, (datetime.datetime, types.NoneType)),
u'maxValue must be a datetime.datetime, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(DateTimeTypeMetadata,
self).__init__(pythonType=datetime.datetime,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'DATE',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPDateTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(DateTimeTypeMetadata, self).AppendXMLNodes(node, document)
#Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
#Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
_RaiseException(NotImplementedError(_(u'Properties or method
parameters of type DateTimeTypeMetadata cannot currently have default
values.')))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if value is not None and not isinstance(value, datetime.datetime):
try:
import pythoncom
except:
pass
else:
if isinstance(value, pythoncom.PyTimeType):
value = datetime.datetime(value.year, value.month,
value.day, value.hour, value.minute, value.second, value.msec)
valueChanged = True
(valueChanged2, value) = super(DateTimeTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)s provided
for the %(variable)s is less than the minimum allowed value %(minValue)s.') %
{u'value' : unicode(value), u'variable' : variableName, u'minValue' :
unicode(self.MinValue)}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)s provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)s.') % {u'value' : unicode(value), u'variable' : variableName,
u'maxValue' : unicode(self.MaxValue)}))
return (valueChanged or valueChanged2, value)
def COMIDLRepresentationOfValue(self, value):
_RaiseException(NotImplementedError(_(u'Properties or method
parameters of type DateTimeTypeMetadata cannot currently have default
values.')))
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(DateTimeTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip().lower()
# Sadly, it appears that ArcGIS passes datetimes in the
locale-specific
# format. I verified this on Windows by switching the Regional and
# Language Options from English (United States) to German (Germany)
and
# observing the datetime string being passed in a different format.
#
# This means we have to try to parse the string in the locale-specific
# format. Sadly Python does not give us much help here. The
# time.strptime function does have some support for parsing
# locale-specific formats (%x and %X) but it does not seem to work on
# Windows (ArcGIS passes dates as mm/dd/YYYY but the function expects
# mm/dd/yy). As a result, we have to exhaustively try to parse
different
# formats. This is really annoying. We could take a dependency on
# mxDateTime but their licensing model is not compatible with ours,
and
# it would be a shame to take the dependency just to parse a datetime.
t = self.ParseDatetimeFromString(s)
if t is None:
_RaiseException(ValueError(_(u'Failed to parse a date/time value
from the string "%(string)s" provided for the %(paramName)s parameter
(parameter number %(paramIndex)i). Please provide a value in a supported
date/time format. If you provide a date but omit the time, midnight is
assumed. You may not provide a time without a date.') % {u'string' : s,
u'paramName' : paramDisplayName, u'paramIndex' : paramIndex}))
return t
@classmethod
def ParseDatetimeFromString(cls, s):
# Order the parsing formats that we will attempt according to whether
# the year, month, or day comes first in the current locale-specific
# date format.
yearFirstFormats = ['%Y/%m/%d',
'%Y-%m-%d',
'%Y-.%m-.%d',
'%y/%m/%d',
'%y-%m-%d',
'%y-.%m-.%d',
'%Y/%m/%d %I:%M:%S %p',
'%Y-%m-%d %I:%M:%S %p',
'%Y.%m.%d %I:%M:%S %p',
'%y/%m/%d %I:%M:%S %p',
'%y-%m-%d %I:%M:%S %p',
'%y.%m.%d %I:%M:%S %p',
'%Y/%m/%d %H:%M:%S',
'%Y-%m-%d %H:%M:%S',
'%Y.%m.%d %H:%M:%S',
'%y/%m/%d %H:%M:%S',
'%y-%m-%d %H:%M:%S',
'%y.%m.%d %H:%M:%S']
dayFirstFormats = ['%d/%m/%Y',
'%d-%m-%Y',
'%d.%m.%Y',
'%d/%m/%y',
'%d-%m-%y',
'%d.%m.%y',
'%d/%m/%Y %I:%M:%S %p',
'%d-%m-%Y %I:%M:%S %p',
'%d.%m.%Y %I:%M:%S %p',
'%d/%m/%y %I:%M:%S %p',
'%d-%m-%y %I:%M:%S %p',
'%d.%m.%y %I:%M:%S %p',
'%d/%m/%Y %H:%M:%S',
'%d-%m-%Y %H:%M:%S',
'%d.%m.%Y %H:%M:%S',
'%d/%m/%y %H:%M:%S',
'%d-%m-%y %H:%M:%S',
'%d.%m.%y %H:%M:%S']
monthFirstFormats = ['%m/%d/%Y',
'%m-%d-%Y',
'%m.%d.%Y',
'%m/%d/%y',
'%m-%d-%y',
'%m.%d.%y',
'%m/%d/%Y %I:%M:%S %p',
'%m-%d-%Y %I:%M:%S %p',
'%m.%d.%Y %I:%M:%S %p',
'%m/%d/%y %I:%M:%S %p',
'%m-%d-%y %I:%M:%S %p',
'%m.%d.%y %I:%M:%S %p',
'%m/%d/%Y %H:%M:%S',
'%m-%d-%Y %H:%M:%S',
'%m.%d.%Y %H:%M:%S',
'%m/%d/%y %H:%M:%S',
'%m-%d-%y %H:%M:%S',
'%m.%d.%y %H:%M:%S']
otherFormats = ['%Y.%m.%d.',
'%Y.%m.%d. %H:%M:%S',
'%Y-%m-%d %I:%M:%S.%p',
'%d/%m %Y',
'%d/%m %Y %H:%M:%S']
localeTimeStr = time.strftime('%x', (2007, 12, 31, 0, 0, 0, 0, 365,
-1))
if localeTimeStr.startswith('2007') or localeTimeStr.startswith('07')
or localeTimeStr.startswith('7'):
formats = yearFirstFormats + dayFirstFormats + monthFirstFormats
+ otherFormats
elif localeTimeStr.startswith('31'):
formats = dayFirstFormats + monthFirstFormats + yearFirstFormats
+ otherFormats
else:
formats = monthFirstFormats + yearFirstFormats + dayFirstFormats
+ otherFormats
# Parse the string using the list of formats.
t = None
for f in formats:
try:
t = time.strptime(s, f)
except:
pass
else:
break
if t is not None:
return datetime.datetime(*t[0:6])
return None
class FloatTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (types.FloatType, types.NoneType)),
u'minValue must be a float, or None'
assert isinstance(maxValue, (types.FloatType, types.NoneType)),
u'maxValue must be a float, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(FloatTypeMetadata, self).__init__(pythonType=types.FloatType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'double',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPDoubleTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(FloatTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'double')).appendChild(document.createTextNode(unicode(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if isinstance(value, types.IntType):
value = float(value)
valueChanged = True
(valueChanged2, value) = super(FloatTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)G provided
for the %(variable)s is less than the minimum allowed value %(minValue)G.') %
{u'value' : value, u'variable' : variableName, u'minValue' : self.MinValue}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)G provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)G.') % {u'value' : value, u'variable' : variableName, u'maxValue'
: self.MaxValue}))
return (valueChanged or valueChanged2, value)
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.FloatType), u'value must be a float'
return str(value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(FloatTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip()
try:
value = float(s)
except Exception, e:
_RaiseException(ValueError(_(u'Failed to parse a floating-point
number from the string "%(string)s" provided for the %(paramName)s parameter
(parameter number %(paramIndex)i). Please provide a string with valid
formatting. The Python float function reported: %(msg)s') % {u'string' : s,
u'paramName' : paramDisplayName, u'paramIndex' : paramIndex, u'msg' :
unicode(e)}))
return value
class IntegerTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (types.IntType, types.NoneType)),
u'minValue must be an integer, or None'
assert isinstance(maxValue, (types.IntType, types.NoneType)),
u'maxValue must be an integer, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(IntegerTypeMetadata, self).__init__(pythonType=types.IntType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'long',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPLongTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(IntegerTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(IntegerTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)i provided
for the %(variable)s is less than the minimum allowed value %(minValue)i.') %
{u'value' : value, u'variable' : variableName, u'minValue' : self.MinValue}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)i provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)i.') % {u'value' : value, u'variable' : variableName, u'maxValue'
: self.MaxValue}))
return (valueChanged, value)
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.IntType), u'value must be an int'
return str(value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(IntegerTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip()
try:
value = int(s)
except Exception, e:
_RaiseException(ValueError(_(u'Failed to parse an integer from
the string "%(string)s" provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). Please provide a string with valid formatting. The
Python integer function reported: %(msg)s') % {u'string' : s, u'paramName' :
paramDisplayName, u'paramIndex' : paramIndex, u'msg' : unicode(e)}))
return value
class UnicodeStringTypeMetadata(TypeMetadata):
def __init__(self,
stripWhitespace=True,
makeLowercase=False,
minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=False,
allowedValues=None,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPStringTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(stripWhitespace, types.BooleanType),
u'stripWhitespace must be a boolean'
assert isinstance(makeLowercase, types.BooleanType), u'makeLowercase
must be a boolean'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
assert isinstance(mustMatchRegEx, (types.NoneType,
types.UnicodeType)), u'mustMatchRegEx must be a Unicode string, or None'
super(UnicodeStringTypeMetadata,
self).__init__(pythonType=types.UnicodeType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'BSTR',
canBeCOMParameter=True,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._StripWhitespace = stripWhitespace
self._MakeLowercase = makeLowercase
self._MinLength = minLength
self._MaxLength = maxLength
self._MustMatchRegEx = mustMatchRegEx
def _GetStripWhitespace(self):
return self._StripWhitespace
StripWhitespace = property(_GetStripWhitespace, doc=DynamicDocString())
def _GetMakeLowercase(self):
return self._MakeLowercase
MakeLowercase = property(_GetMakeLowercase, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def _GetMustMatchRegEx(self):
return self._MustMatchRegEx
MustMatchRegEx = property(_GetMustMatchRegEx, doc=DynamicDocString())
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.UnicodeType), u'value must be a
Unicode string'
return '"' + str(value).replace('"', '\\"') + '"'
def AppendXMLNodes(self, node, document):
super(UnicodeStringTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'StripWhitespace', node,
document)
Metadata.AppendPropertyXMLNode(self, u'MakeLowercase', node, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MustMatchRegEx', node,
document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'string')).appendChild(document.createTextNode(value))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if isinstance(value, types.StringType):
value = unicode(value)
valueChanged = True
(valueChanged2, value) = super(UnicodeStringTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
valueChanged = valueChanged or valueChanged2
if value is not None:
if self.StripWhitespace:
value = value.strip()
valueChanged = True
if self.MakeLowercase:
value = value.lower()
valueChanged = True
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is too short. It may be no shorter than %(len)i characters.') %
{u'variable' : variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is too long. It may be no longer than %(len)i characters.') %
{u'variable' : variableName, u'len' : self.MaxLength}))
if self.MustMatchRegEx is not None and not
re.match(self.MustMatchRegEx, value):
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is not formatted properly. Please check the documentation for
the %(variable)s for details on the format. (Technical details: the value did
not match the regular expression "%(regex)s".)') % {u'variable' :
variableName, u'regex' : self.MustMatchRegEx}))
return (valueChanged, value)
# Python sequence types
class SequenceTypeMetadata(TypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
pythonType=types.ObjectType,
canBeNone=False,
comIDLType=None,
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=False):
assert isinstance(elementType, TypeMetadata), u'elementType must be
an instance of TypeMetadata'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
assert isinstance(maxItemsToValidate, types.IntType) and
maxItemsToValidate >= 0, u'maxItemsToValidate must be an integer greater than
or equal to 0'
assert isinstance(mustBeSameLengthAsArgument, (types.UnicodeType,
types.NoneType)), u'mustBeSameLengthAsArgument must be a Unicode string, or
None'
assert not canBeArcGISInputParameter or not arcGISType !=
u'ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass' or
(issubclass(elementType.PythonType, basestring) or not
hasattr(elementType.PythonType, '__getitem__')), u'For this sequence type to
be passed as an ArcGIS input parameter using the ArcGIS data type
ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass, its elements may not
themselves be sequences unless they are strings. (In other words, you can\'t
pass nested sequences using ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass.)'
# If comIDLType is None and canBeCOMParameter is True, which is
# the normal situation, set comIDLType to a SAFEARRAY of the proper
IDL
# type for the elementType.
if comIDLType is None and canBeCOMParameter:
t = elementType
while isinstance(t, SequenceTypeMetadata):
t = t.ElementType
comIDLType = u'SAFEARRAY(%s)' % t.COMIDLType
# Initialize the base class.
super(SequenceTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone,
comIDLType=comIDLType,
canBeCOMParameter=canBeCOMParameter,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._ElementType = elementType
self._MinLength = minLength
self._MaxLength = maxLength
self._MaxItemsToValidate = maxItemsToValidate
self._MustBeSameLengthAsArgument = mustBeSameLengthAsArgument
def _GetElementType(self):
return self._ElementType
ElementType = property(_GetElementType, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def _GetMaxItemsToValidate(self):
return self._MaxItemsToValidate
MaxItemsToValidate = property(_GetMaxItemsToValidate,
doc=DynamicDocString())
def _GetMustBeSameLengthAsArgument(self):
return self._MustBeSameLengthAsArgument
MustBeSameLengthAsArgument = property(_GetMustBeSameLengthAsArgument,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(SequenceTypeMetadata, self).AppendXMLNodes(node, document)
elementTypeNode =
node.appendChild(document.createElement(u'ElementTypeMetadata'))
self.ElementType.AppendXMLNodes(elementTypeNode, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxItemsToValidate', node,
document)
Metadata.AppendPropertyXMLNode(self, u'MustBeSameLengthAsArgument',
node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
listNode = node.appendChild(document.createElement(u'ArrayList'))
for element in value:
self.ElementType.AppendXMLNodesForValue(element, listNode,
document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(SequenceTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
length1 = 0
length2 = 0
if value is not None:
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too short. It must contain at least %(len)i items.') % {u'variable' :
variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too long. It must contain no more than %(len)i items.') % {u'variable' :
variableName, u'len' : self.MaxLength}))
if self.MustBeSameLengthAsArgument is not None and methodLocals
is not None:
assert methodLocals.has_key(self.MustBeSameLengthAsArgument),
_(u'To validate the %(param1)s of the method being validated, that method
must also have an parameter named %(param2)s.') % {u'param1' : variableName,
u'param2' : self.MustBeSameLengthAsArgument}
length1 = len(value)
if self.MustBeSameLengthAsArgument is not None and methodLocals
is not None and methodLocals[self.MustBeSameLengthAsArgument] is not None:
try:
length2 =
len(methodLocals[self.MustBeSameLengthAsArgument])
except Exception, e:
_RaiseException(TypeError(_(u'To validate the %(param1)s
of the method being validated, the length of method\'s %(param2)s parameter
must be able to be obtained with the Python len function. That function
raised the following exception when passed the value of that parameter:
%(error)s: %(msg)s') % {u'param1' : variableName, u'param2' :
self.MustBeSameLengthAsArgument, u'error': e.__class__.__name__, u'msg':
unicode(e)}))
if length1 != length2:
_RaiseException(TypeError(_(u'The %(param1)s must have the
same number of items as the %(param2)s parameter.') % {u'param1' :
variableName, u'param2' : self.MustBeSameLengthAsArgument}))
return (valueChanged, value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
paramString = super(SequenceTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex)
# The input string is a list of values formatted as follows:
# - Values are separated by semicolons
# - If a value contains a space or tab it is enclosed in
apostrophes
# - There are no escape sequences for semicolons or apostrophes
# - An empty string is formatted as two successive semicolons
#
# We parse the string using a finite state machine. Because there are
no
# escape sequences for semicolons or apostrophes, it is not possible
for
# the user to pass certain strings to us, and some strings will lead
to
# undesirable results.
FIRST_CHARACTER = 1 # We are
positioned on the first character of the input strong or the first character
following the semicolon that terminated the previous element.
INSIDE_SEMICOLON = 2 # We are
positioned on the second or subsequent character inside an element that did
not begin with an apostrophe.
INSIDE_QUOTE_NO_SPACE_FOUND = 3 # We are
positioned on the second or subsequent character inside an element that began
with an apostrophe, and we have not yet found the space or tab character that
necessitated the apostrophe, so it could just be part of the string.
INSIDE_QUOTE_SPACE_FOUND = 4 # We are
positioned on the second or subsequent character inside an element that began
with an apostrophe, and we have already found the space or tab character that
necessitated the apostrophe.
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE = 5 # We are
positioned on a character following the second or subsequent apostrophe
inside an element that begain with an apostrophe and was found to have a
space or tab character. The apostrophe we just parsed could be the closing
apostrophe, if we now are positioned on a semicolon or the end of the string.
state = FIRST_CHARACTER
params = []
i = 0
paramStart = 0
paramCharCount = 0
failedBecauseArcGISForgotQuotes = False # Sometimes ArcGIS seems
to violate the rules described above in a way that makes the string
unparsable. In this case we treat it as a single string and report a warning.
#from GeoEco.Logging import Logger
try:
while i < len(paramString):
#Logger.Debug('----------------------------')
#Logger.Debug(u'i = %i, c = %s, state = %i, paramStart = %i,
paramCharCount= %i' % (i, paramString[i], state, paramStart, paramCharCount))
if state == FIRST_CHARACTER:
if paramString[i] == u';':
params.append(u'')
elif paramString[i] == u'\'':
state = INSIDE_QUOTE_NO_SPACE_FOUND
paramStart = i
paramCharCount = 1
else:
state = INSIDE_SEMICOLON
paramStart = i
paramCharCount = 1
elif state == INSIDE_SEMICOLON:
if paramString[i] == u' ' or paramString[i] == u'\t':
failedBecauseArcGISForgotQuotes = True
raise ValueError(_(u'Failed to parse a list of values
from the string provided for the %(paramName)s parameter (parameter number
%(paramIndex)i). The parser encountered an error: a space or tab character
was found outside of enclosing apostrophes. If an element in the list
contains a space or tab, enclose the entire element in apostrophes. If you
are invoking this function from ArcGIS, there is no need to do this
explicitly, ArcGIS does it for you; you must have received this error for a
different reason. Please contact the author of this function for
assistance.') % {u'paramName' : paramDisplayName, u'paramIndex' : paramIndex})
elif paramString[i] == u';':
state = FIRST_CHARACTER
params.append(paramString[paramStart:paramStart+paramCharCount])
else:
paramCharCount += 1
elif state == INSIDE_QUOTE_NO_SPACE_FOUND:
if paramString[i] == u';':
state = FIRST_CHARACTER
if paramString[paramStart:paramStart+paramCharCount]
== u'\'\'':
params.append(u'')
else:
params.append(paramString[paramStart:paramStart+paramCharCount])
elif paramString[i] == u' ' or paramString[i] == u'\t':
state = INSIDE_QUOTE_SPACE_FOUND
paramStart += 1
else:
paramCharCount += 1
elif state == INSIDE_QUOTE_SPACE_FOUND:
if paramString[i] == u'\'':
state =
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE
else:
paramCharCount += 1
elif state ==
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE:
if paramString[i] == u'\'':
paramCharCount += 1
elif paramString[i] == u';':
state = FIRST_CHARACTER
params.append(paramString[paramStart:paramStart+paramCharCount])
else:
paramCharCount += 1
else:
_RaiseException(RuntimeError(_(u'Failed to parse a list
of values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i) due to a programming error in the parser: the parser
was found to be in unknown state %(state)i. Please contact the author of this
function for assistance.') % {u'paramName' : paramDisplayName, u'paramIndex'
: paramIndex, u'state' : state}))
#Logger.Debug('state = %i, paramStart = %i, paramCharCount=
%i' % (state, paramStart, paramCharCount))
i += 1
except:
if failedBecauseArcGISForgotQuotes:
from GeoEco.Logging import Logger
Logger.Warning(_(u'The string provided for %(paramName)s
parameter (parameter number %(paramIndex)i) included a space but the string
itself was not enclosed in apostrophes. This is a known problem with how
ArcGIS passes parameters to Python scripts. As a result, the string cannot be
parsed into a list of items and will be treated as a single item. This may
result in unintended effects. Please check your outputs carefully.') %
{u'paramName' : paramDisplayName, u'paramIndex' : paramIndex})
params.append(paramString)
else:
raise
else:
if state == FIRST_CHARACTER:
if paramString.endswith(u';'):
params.append(u'')
elif state == INSIDE_SEMICOLON or state ==
INSIDE_QUOTE_NO_SPACE_FOUND or state ==
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE:
params.append(paramString[paramStart:paramStart+paramCharCount])
elif state == INSIDE_QUOTE_SPACE_FOUND:
_RaiseException(ValueError(_(u'Failed to parse a list of
values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). The parser encountered an error: the last element in
the list begain with an apostrophe, included at least one space or tab
character but did not end with an apostrophe. Please end your string with an
apostrophe. If you are invoking this function from ArcGIS, there is no need
to do this explicitly, ArcGIS does it for you; you must have received this
error for a different reason. Please contact the author of this function for
assistance.') % {u'paramName' : paramDisplayName, u'paramIndex' :
paramIndex}))
else:
_RaiseException(RuntimeError(_(u'Failed to parse a list of
values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i) due to a programming error in the parser: the parser
was found to be in unknown state %(state)i. Please contact the author of this
function for assistance.') % {u'paramName' : paramDisplayName, u'paramIndex'
: paramIndex, u'state' : state}))
# The parser built a list of Unicode strings. If we're supposed to
# return a list of Unicode strings, just return now.
if issubclass(self.ElementType.PythonType, types.UnicodeType):
return params
# Parse the list of Unicode strings into the appropriate Python type.
# For Python types that are not strings, we interpret whitespace as
# None.
values = []
for i in range(len(params)):
s = params[i]
if not issubclass(self.ElementType.PythonType, types.StringType):
s = params[i].strip()
if len(s) <= 0 and self.ElementType.CanBeNone:
values.append(None)
continue
values.append(self.ElementType.ParseValueFromArcGISInputParameterString(s,
_(u'element at position %i (where 0 is the first element) of the %s') % (i,
paramDisplayName), paramIndex))
return values
class ListTypeMetadata(SequenceTypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
canBeNone=False):
super(ListTypeMetadata, self).__init__(elementType=elementType,
minLength=minLength,
maxLength=maxLength,
maxItemsToValidate=maxItemsToValidate,
mustBeSameLengthAsArgument=mustBeSameLengthAsArgument,
pythonType=types.ListType,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ListTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
itemsToValidate = min(len(value), self.MaxItemsToValidate)
if itemsToValidate != len(value):
from GeoEco.Logging import Logger
Logger.Debug(_(u'The %(var)s contains %(count1)i items, but
to minimize execution time, only the first %(count2)i items will be
validated. If an invalid item is present, unexpected results may occur.') %
{u'var': variableName, u'count1': len(value), u'count2':
self.MaxItemsToValidate})
for i in range(itemsToValidate):
(elementValueChanged, newElementValue) =
self.ElementType.ValidateValue(value[i], _(u'element %i of the %s (where 0 is
the first element)') % (i, variableName), methodLocals, argMetadata)
if elementValueChanged:
value[i] = newElementValue
valueChanged = True
return (valueChanged, value)
class TupleTypeMetadata(SequenceTypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
canBeNone=False):
super(TupleTypeMetadata, self).__init__(elementType=elementType,
minLength=minLength,
maxLength=maxLength,
maxItemsToValidate=maxItemsToValidate,
mustBeSameLengthAsArgument=mustBeSameLengthAsArgument,
pythonType=types.TupleType,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(TupleTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
itemsToValidate = min(len(value), self.MaxItemsToValidate)
if itemsToValidate != len(value):
from GeoEco.Logging import Logger
Logger.Debug(_(u'The %(var)s contains %(count1)i items, but
to minimize execution time, only the first %(count2)i items will be
validated. If an invalid item is present, unexpected results may occur.') %
{u'var': variableName, u'count1': len(value), u'count2':
self.MaxItemsToValidate})
for i in range(itemsToValidate):
(elementValueChanged, newElementValue) =
self.ElementType.ValidateValue(value[i], _(u'element %i of the %s (where 0 is
the first element)') % (i, variableName), methodLocals, argMetadata)
if elementValueChanged:
if isinstance(value, types.TupleType):
value = list(value)
value[i] = newElementValue
valueChanged = True
if isinstance(value, types.ListType):
value = tuple(value)
valueChanged = True
return (valueChanged, value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
resultList = super(TupleTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex)
return tuple(resultList)
class DictionaryTypeMetadata(TypeMetadata):
def __init__(self,
keyType,
valueType,
minLength=0,
maxLength=2147483647,
pythonType=types.DictType,
canBeNone=False):
assert isinstance(keyType, TypeMetadata), u'keyType must be an
instance of TypeMetadata'
assert isinstance(valueType, TypeMetadata), u'valueType must be an
instance of TypeMetadata'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
# Initialize the base class.
super(DictionaryTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone)
self._KeyType = keyType
self._ValueType = valueType
self._MinLength = minLength
self._MaxLength = maxLength
def _GetKeyType(self):
return self._KeyType
KeyType = property(_GetKeyType, doc=DynamicDocString())
def _GetValueType(self):
return self._ValueType
ValueType = property(_GetValueType, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(DictionaryTypeMetadata, self).AppendXMLNodes(node, document)
keyTypeNode =
node.appendChild(document.createElement(u'KeyTypeMetadata'))
self.KeyType.AppendXMLNodes(keyTypeNode, document)
valueTypeNode =
node.appendChild(document.createElement(u'ValueTypeMetadata'))
self.ValueType.AppendXMLNodes(valueTypeNode, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
def AppendXMLNodesForValue(self, value, node, document):
raise AssertionError(u'Default values are not currently supported for
parameters of type DictionaryTypeMetadata. Please remove the default value
%s.' % unicode(repr(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(DictionaryTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too short. It must contain at least %(len)i items.') % {u'variable' :
variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too long. It must contain no more than %(len)i items.') % {u'variable' :
variableName, u'len' : self.MaxLength}))
for key, val in value.items():
(keyChanged, newKey) = self.ValueType.ValidateValue(val,
_(u'key %s of the %s') % (unicode(repr(key)), variableName), methodLocals,
argMetadata)
(valChanged, newVal) = self.ValueType.ValidateValue(val,
_(u'value of key %s of the %s') % (unicode(repr(key)), variableName),
methodLocals, argMetadata)
if keyChanged and valChanged:
del value[key]
value[newKey] = newVal
elif keyChanged and not valChanged:
del value[key]
value[newKey] = val
elif not keyChanged and valChanged:
value[key] = newVal
valueChanged = keyChanged or valChanged
return (valueChanged, value)
# Types that represents stored objects (files, directories, DB tables, etc.)
class StoredObjectTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self,
typeDisplayName,
isPath=True,
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPStringTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(typeDisplayName, types.UnicodeType),
u'typeDisplayName must be a Unicode string'
assert isinstance(isPath, types.BooleanType), u'isPath must be a
boolean'
assert isinstance(canBeRelativePath, types.BooleanType),
u'canBeRelativePath must be a boolean'
assert not (canBeRelativePath and not isPath), u'If canBeRelativePath
is True, isPath must also be True'
assert isinstance(basePathArgument, (types.UnicodeType,
types.NoneType)), u'basePathArgument must be a Unicode string, or None'
assert not (basePathArgument is not None and not canBeRelativePath),
u'If basePathArgument is not None, canBeRelativePath must also be True'
assert isinstance(useArcGISWorkspace, types.BooleanType),
u'useArcGISWorkspace must be a boolean'
assert not (useArcGISWorkspace and not canBeRelativePath), u'If
useArcGISWorkspace is True, canBeRelativePath must also be True'
assert isinstance(normalizePath, types.BooleanType), u'normalizePath
must be a boolean'
assert isinstance(mustExist, types.BooleanType), u'mustExist must be
a boolean'
assert isinstance(mustNotExist, types.BooleanType), u'mustNotExist
must be a boolean'
assert not mustExist or not mustNotExist, u'mustExist and
mustNotExist cannot both be True'
assert isinstance(deleteIfParameterIsTrue, (types.UnicodeType,
types.NoneType)), u'deleteIfParameterIsTrue must be a Unicode string, or None'
assert not mustNotExist or deleteIfParameterIsTrue is None,
u'deleteIfParameterIsTrue must be None if mustNotExist is True'
assert isinstance(createParentDirectories, types.BooleanType),
u'createParentDirectories must be a boolean'
super(StoredObjectTypeMetadata, self).__init__(minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._TypeDisplayName = typeDisplayName
self._IsPath = isPath
self._CanBeRelativePath = canBeRelativePath
self._BasePathArgument = basePathArgument
self._UseArcGISWorkspace = useArcGISWorkspace
self._NormalizePath = normalizePath
self._MustBeDifferentThanArguments = mustBeDifferentThanArguments
self._MustExist = mustExist
self._MustNotExist = mustNotExist
self._DeleteIfParameterIsTrue = deleteIfParameterIsTrue
self._CreateParentDirectories = createParentDirectories
def _GetTypeDisplayName(self):
return self._TypeDisplayName
TypeDisplayName = property(_GetTypeDisplayName, doc=DynamicDocString())
def _GetIsPath(self):
return self._IsPath
IsPath = property(_GetIsPath, doc=DynamicDocString())
def _GetCanBeRelativePath(self):
return self._CanBeRelativePath
CanBeRelativePath = property(_GetCanBeRelativePath,
doc=DynamicDocString())
def _GetBasePathArgument(self):
return self._BasePathArgument
def _SetBasePathArgument(self, value):
assert isinstance(value, (types.UnicodeType, types.NoneType)),
u'BasePathArgument must be a Unicode string, or None'
self._BasePathArgument = value
BasePathArgument = property(_GetBasePathArgument, _SetBasePathArgument,
doc=DynamicDocString())
def _GetUseArcGISWorkspace(self):
return self._UseArcGISWorkspace
UseArcGISWorkspace = property(_GetUseArcGISWorkspace,
doc=DynamicDocString())
def _GetNormalizePath(self):
return self._NormalizePath
NormalizePath = property(_GetNormalizePath, doc=DynamicDocString())
def _GetMustBeDifferentThanArguments(self):
return self._MustBeDifferentThanArguments
def _SetMustBeDifferentThanArguments(self, value):
assert isinstance(value, (types.ListType, types.TupleType,
types.NoneType)), u'MustBeDifferentThanArguments must be a list or tuple of
Unicode strings, or None'
if value is not None:
if isinstance(value, types.TupleType):
value = list(value)
for v in value:
assert isinstance(value, types.UnicodeType),
u'MustBeDifferentThanArguments must be a list or tuple of Unicode strings, or
None'
self._MustBeDifferentThanArguments = value
MustBeDifferentThanArguments = property(_GetMustBeDifferentThanArguments,
_SetMustBeDifferentThanArguments, doc=DynamicDocString())
def _GetMustExist(self):
return self._MustExist
def _SetMustExist(self, value):
assert isinstance(value, types.BooleanType), u'MustExist must be a
boolean'
self._MustExist = value
MustExist = property(_GetMustExist, _SetMustExist, doc=DynamicDocString())
def _GetMustNotExist(self):
return self._MustNotExist
def _SetMustNotExist(self, value):
assert isinstance(value, types.BooleanType), u'MustNotExist must be a
boolean'
self._MustNotExist = value
MustNotExist = property(_GetMustNotExist, _SetMustNotExist,
doc=DynamicDocString())
def _GetDeleteIfParameterIsTrue(self):
return self._DeleteIfParameterIsTrue
def _SetDeleteIfParameterIsTrue(self, value):
assert isinstance(value, (types.UnicodeType, types.NoneType)),
u'DeleteIfParameterIsTrue must be a Unicode string, or None'
self._DeleteIfParameterIsTrue = value
DeleteIfParameterIsTrue = property(_GetDeleteIfParameterIsTrue,
_SetDeleteIfParameterIsTrue, doc=DynamicDocString())
def _GetCreateParentDirectories(self):
return self._CreateParentDirectories
def _SetCreateParentDirectories(self, value):
assert isinstance(value, types.BooleanType),
u'CreateParentDirectories must be a boolean'
self._CreateParentDirectories = value
CreateParentDirectories = property(_GetCreateParentDirectories,
_SetCreateParentDirectories, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(StoredObjectTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'TypeDisplayName', node,
document)
Metadata.AppendPropertyXMLNode(self, u'IsPath', node, document)
Metadata.AppendPropertyXMLNode(self, u'CanBeRelativePath', node,
document)
Metadata.AppendPropertyXMLNode(self, u'BasePathArgument', node,
document)
Metadata.AppendPropertyXMLNode(self, u'UseArcGISWorkspace', node,
document)
Metadata.AppendPropertyXMLNode(self, u'NormalizePath', node, document)
mustBeDifferentThanArgumentsNode =
node.appendChild(document.createElement(u'MustBeDifferentThanArguments'))
if self.MustBeDifferentThanArguments is not None:
listNode =
mustBeDifferentThanArgumentsNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.MustBeDifferentThanArguments)):
self.AppendXMLNodesForValue(self.MustBeDifferentThanArguments[i], listNode,
document)
Metadata.AppendPropertyXMLNode(self, u'MustExist', node, document)
Metadata.AppendPropertyXMLNode(self, u'MustNotExist', node, document)
Metadata.AppendPropertyXMLNode(self, u'DeleteIfParameterIsTrue',
node, document)
Metadata.AppendPropertyXMLNode(self, u'CreateParentDirectories',
node, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(StoredObjectTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
exists = None
isCorrectType = None
if self.IsPath:
valueChanged, value, exists, isCorrectType =
self._CanonicalizePath(value, argMetadata, methodLocals)
if self.MustBeDifferentThanArguments is not None and methodLocals
is not None:
for arg in self.MustBeDifferentThanArguments:
assert methodLocals.has_key(arg), _(u'To validate the
%(param1)s of the method being validated, that method must also have an
parameter named %(param2)s.') % {u'param1' : variableName, u'param2' : arg}
if value == methodLocals[arg]:
same = True
elif hasattr(os.path,'samefile'):
try:
same = os.path.samefile(value, methodLocals[arg])
except OSError:
same = False
else:
same = os.path.normcase(os.path.abspath(value)) ==
os.path.normcase(os.path.abspath(methodLocals[arg]))
if same:
_RaiseException(ValueError(_(u'The %(param1)s and the
%(param2)s parameter refer to the same %(type)s (%(value)s). You must not
specify the same %(type)s.') % {u'param1' : variableName, u'param2' : arg,
u'type' : self.TypeDisplayName, u'value' : value}))
from GeoEco.Logging import Logger
oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
Logger.SetLogInfoAsDebug(True)
try:
if self.MustExist or self.MustNotExist or
self.DeleteIfParameterIsTrue is not None:
assert self.DeleteIfParameterIsTrue is None or
methodLocals.has_key(self.DeleteIfParameterIsTrue), _(u'To validate the
%(param1)s of the method being validated, that method must also have an
parameter named %(param2)s.') % {u'param1' : variableName, u'param2' :
self.DeleteIfParameterIsTrue}
if exists is None:
exists, isCorrectType = self.Exists(value,
argMetadata, methodLocals)
if exists:
if isCorrectType:
if self.MustNotExist or
self.DeleteIfParameterIsTrue is not None and not
methodLocals[self.DeleteIfParameterIsTrue]:
_RaiseException(ValueError(_(u'The %(type)s
%(value)s, specified for the %(variable)s, already exists. Please delete it
and try again, or specify a non-existing %(type)s.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName}))
if self.DeleteIfParameterIsTrue is not None and
methodLocals[self.DeleteIfParameterIsTrue]:
self.Delete(value, argMetadata, methodLocals)
else:
if self.MustNotExist:
_RaiseException(ValueError(_(u'The value
specified for the %(variable)s, %(value)s, already exists although it is not
a %(type)s. Please delete it and try again, or specify a non-existing
object.') % {u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName}))
if self.MustExist or self.DeleteIfParameterIsTrue
is not None:
_RaiseException(ValueError(_(u'The value
specified for the %(variable)s, %(value)s, exists but it is not a %(type)s.
Please specify a %(type)s.') % {u'type' : self.TypeDisplayName, u'value' :
value, u'variable' : variableName}))
elif self.MustExist:
_RaiseException(ValueError(_(u'The %(type)s
%(value)s, specified for the %(variable)s, does not exist. Please specify an
existing %(type)s.') % {u'type' : self.TypeDisplayName, u'value' : value,
u'variable' : variableName}))
if self.CreateParentDirectories and
(re.match(u'^[A-Za-z]:[\\\\/]', value) or re.match(u'^[\\\\/]', value)) and
not (os.path.dirname(value).lower().endswith(u'.mdb') and
os.path.isfile(os.path.dirname(value))):
from GeoEco.DataManagement.Directories import Directory
Directory.Create(os.path.dirname(value))
finally:
Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
return (valueChanged, value)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
valueChanged = False
if self.IsRelativePath(value):
if not self.CanBeRelativePath:
_RaiseException(ValueError(_(u'The %(variable)s specifies the
relative path "%(value)s" but relative paths are not allowed. Please provide
an absolute path and try again.') % {u'variable' : variableName, u'value' :
value}))
madeAbsolute = False
if self.BasePathArgument is not None:
if not methodLocals.has_key(self.BasePathArgument):
_RaiseException(RuntimeError(_(u'Programming error in
this tool. The metadata for the %(variable)s specifies that when the caller
provides a relative path, the base path can be obtained from the %(base)s
parameter, but that parameter does not exist. Please contact the author of
this tool for assistance.') % {u'variable' : variableName, u'base':
self.BasePathArgument}))
if methodLocals[self.BasePathArgument] is not None:
value2 =
os.path.join(methodLocals[self.BasePathArgument], value)
if value != value2:
value = value2
valueChanged = True
madeAbsolute = True
if not madeAbsolute and self.UseArcGISWorkspace:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp is not None and isinstance(gp.Workspace, basestring)
and len(gp.Workspace) > 0:
value2 = os.path.join(gp.Workspace, value)
if value != value2:
value = value2
valueChanged = True
madeAbsolute = True
if not madeAbsolute:
value2 = os.path.abspath(value)
if value != value2:
value = value2
valueChanged = True
if self.NormalizePath:
value2 = os.path.normpath(value)
if value != value2:
value = value2
valueChanged = True
return valueChanged, value, None, None # valueChanged, value,
exists, isCorrectType
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Exists method.' % className))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Delete method.' % className))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Copy method.' % className))
@classmethod
def IsRelativePath(cls, p):
if p is None:
return False
if sys.platform == u'win32':
if re.match(u'^[A-Za-z]:[\\\\/]', p) or
re.match(u'^[\\\\/][\\\\/]\w', p):
return False
else:
if p.startswith(u'/'):
return False
return True
class FileTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
mayBeCompressed=False,
decompressedFileToUse=u'*',
typeDisplayName=_(u'file'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(mayBeCompressed, types.BooleanType),
u'mayBeCompressed must be a boolean'
super(FileTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._MayBeCompressed = mayBeCompressed
self._DecompressedFileToUse = decompressedFileToUse
def _GetMayBeCompressed(self):
return self._MayBeCompressed
MayBeCompressed = property(_GetMayBeCompressed, doc=DynamicDocString())
def _GetDecompressedFileToUse(self):
return self._DecompressedFileToUse
DecompressedFileToUse = property(_GetDecompressedFileToUse,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(FileTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MayBeCompressed', node,
document)
Metadata.AppendPropertyXMLNode(self, u'DecompressedFileToUse', node,
document)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Files import File
return File.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Files import File
File.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Files import File
File.Copy(source, dest, overwriteExisting=overwriteExisting)
class TextFileTypeMetadata(FileTypeMetadata):
def __init__(self,
mayBeCompressed=False,
decompressedFileToUse=u'*',
typeDisplayName=_(u'text file'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DETextFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(TextFileTypeMetadata,
self).__init__(mayBeCompressed=mayBeCompressed,
decompressedFileToUse=decompressedFileToUse,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
class DirectoryTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'directory'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEFolderTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(DirectoryTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
return Directory.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
Directory.Delete(name, removeTree=True)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
Directory.Copy(source, dest,
deleteExistingDestinationDirectory=overwriteExisting,
overwriteExistingFiles=overwriteExisting)
# ArcGIS types
class ArcGISGeoDatasetTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'geographic dataset'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.DEGeoDatasetTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISGeoDatasetTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISGeoDatasetTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
# See if it exists.
from GeoEco.Logging import Logger
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp is None:
Logger.RaiseException(RuntimeError(_(u'The ArcGIS geoprocessor
must be initialized before this function may be called. Please call
GeoprocessorManager.InitializeGeoprocessor or
GeoprocessorManager.SetGeoprocessor before calling this function.')))
exists = gp.Exists(name)
isCorrectType = False
# If it exists, see if the describe object has an Extent
# property. If it does, then it is a "geodataset".
if exists:
d = gp.Describe(name)
isCorrectType = d is not None and hasattr(d, 'Extent') and
isinstance(d.Extent, basestring) and len(d.Extent) > 0
# Log a debug message indicating what happened.
if not exists:
Logger.Debug(_(u'The geographic dataset %(path)s does not
exist.') % {u'path': name})
else:
if isCorrectType:
Logger.Debug(_(u'The geographic dataset %(path)s exists.') %
{u'path': name})
else:
Logger.Debug(_(u'%(path)s exists but it is a %(actual)s, not
a geographic dataset.') % {u'path': name, u'actual': d.DataType})
# Return the results.
return (exists, isCorrectType)
class ArcGISRasterTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedPixelTypes=None,
typeDisplayName=_(u'raster'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.DataSourcesRaster.DERasterDatasetTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.DataSourcesRaster',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedPixelTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedPixelTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedPixelTypes, types.TupleType):
allowedPixelTypes = list(allowedPixelTypes)
if allowedPixelTypes is not None:
for s in allowedPixelTypes:
assert isinstance(s, types.UnicodeType), u'allowedPixelTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedPixelTypes = map(unicode.strip, map(unicode.lower,
allowedPixelTypes))
else:
self._AllowedPixelTypes = None
super(ArcGISRasterTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedPixelTypes(self):
return self._AllowedPixelTypes
AllowedPixelTypes = property(_GetAllowedPixelTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISRasterTypeMetadata, self).AppendXMLNodes(node, document)
allowedPixelTypesNode =
node.appendChild(document.createElement(u'AllowedPixelTypes'))
if self.AllowedPixelTypes is not None:
listNode =
allowedPixelTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedPixelTypes)):
self.AppendXMLNodesForValue(self.AllowedPixelTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISRasterTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedPixelTypes is not None:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp.Exists(value) and gp.Describe(value).PixelType.lower() not
in self.AllowedPixelTypes:
if len(self.AllowedPixelTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, is a %(pt)s %(type)s but this function
requires a %(allowed)s %(type)s. Please provide a %(allowed)s %(type)s.') %
{u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName, u'pt': self.GetPixelTypeName(gp.Describe(value).PixelType),
u'allowed': self.GetPixelTypeName(self.AllowedPixelTypes[0])}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, is a %(pt)s %(type)s but this function
requires a %(type)s with one of the following pixel types: %(allowed)s.
Please provide a %(type)s with an allowed pixel type.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName, u'pt':
self.GetPixelTypeName(gp.Describe(value).PixelType), u'allowed': unicode('\',
\''.join(map(self.GetPixelTypeName, self.AllowedPixelTypes)))}))
return (valueChanged, value)
def GetPixelTypeName(self, pixelType):
name = _(u'unknown data type')
if isinstance(pixelType, basestring) and len(pixelType) >= 2:
if pixelType[0] == u'u' or pixelType[0] == u'U':
name = _('%s-bit unsigned integer') % pixelType[1:]
elif pixelType[0] == u's' or pixelType[0] == u'S':
name = _('%s-bit signed integer') % pixelType[1:]
elif pixelType[0] == u'f' or pixelType[0] == u'F':
name = _('%s-bit floating point') % pixelType[1:]
return name
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
return ArcGISRaster.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
ArcGISRaster.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
ArcGISRaster.Copy(source, dest, overwriteExisting=overwriteExisting)
class ArcGISRasterLayerTypeMetadata(ArcGISRasterTypeMetadata):
def __init__(self,
allowedPixelTypes=None,
typeDisplayName=_(u'raster or raster layer'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPRasterLayerTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISRasterLayerTypeMetadata,
self).__init__(allowedPixelTypes=allowedPixelTypes,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISRasterLayerTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name,
[u'rasterdataset', u'rasterlayer', u'rasterband'], _(u'ArcGIS raster, raster
layer, or raster band'))
class ArcGISFeatureClassTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedShapeTypes=None,
typeDisplayName=_(u'feature class'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DEFeatureClassTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedShapeTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedShapeTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedShapeTypes, types.TupleType):
allowedShapeTypes = list(allowedShapeTypes)
if allowedShapeTypes is not None:
for s in allowedShapeTypes:
assert isinstance(s, types.UnicodeType), u'allowedShapeTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedShapeTypes = map(unicode.strip, map(unicode.lower,
allowedShapeTypes))
else:
self._AllowedShapeTypes = None
super(ArcGISFeatureClassTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedShapeTypes(self):
return self._AllowedShapeTypes
AllowedShapeTypes = property(_GetAllowedShapeTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISFeatureClassTypeMetadata, self).AppendXMLNodes(node,
document)
allowedShapeTypesNode =
node.appendChild(document.createElement(u'AllowedShapeTypes'))
if self.AllowedShapeTypes is not None:
listNode =
allowedShapeTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedShapeTypes)):
self.AppendXMLNodesForValue(self.AllowedShapeTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISFeatureClassTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedShapeTypes is not None:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp.Exists(value) and gp.Describe(value).ShapeType.lower() not
in self.AllowedShapeTypes:
if len(self.AllowedShapeTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the shape type \'%(shape)s\', but this
function requires a %(type)s with the shape type \'%(allowed)s\'. Please
provide a %(type)s with shape type \'%(allowed)s\'.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName, u'shape':
gp.Describe(value).ShapeType.lower(), u'allowed': self.AllowedShapeTypes[0]}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the shape type \'%(shape)s\', but this
function requires a %(type)s with one of the following shape types:
\'%(allowed)s\'. Please provide a %(type)s with an allowed shape type.') %
{u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName, u'shape': gp.Describe(value).ShapeType.lower(), u'allowed':
unicode('\', \''.join(map(str, self.AllowedShapeTypes)))}))
return (valueChanged, value)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'featureclass',
u'shapefile'], _(u'ArcGIS feature class'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'featureclass',
u'shapefile'], _(u'ArcGIS feature class'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'featureclass', u'shapefile'], _(u'ArcGIS feature class'))
class ArcGISFeatureLayerTypeMetadata(ArcGISFeatureClassTypeMetadata):
def __init__(self,
allowedShapeTypes=None,
typeDisplayName=_(u'feature class or layer'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPFeatureLayerTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISFeatureLayerTypeMetadata,
self).__init__(allowedShapeTypes=allowedShapeTypes,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISFeatureLayerTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'featureclass',
u'shapefile', u'featurelayer'], _(u'ArcGIS feature class or layer'))
class ShapefileTypeMetadata(FileTypeMetadata):
def __init__(self,
typeDisplayName=_(u'shapefile'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=u'.+\.[Ss][Hh][Pp]$',
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEShapeFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ShapefileTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
return Shapefile.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
Shapefile.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
Shapefile.Copy(source, dest, overwriteExisting=overwriteExisting)
class ArcGISWorkspaceTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'workspace'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DEWorkspaceTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISWorkspaceTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'workspace',
u'folder'], _(u'ArcGIS workspace'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'workspace',
u'folder'], _(u'ArcGIS workspace'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'workspace', u'folder'], _(u'ArcGIS workspace'))
class ArcGISTableTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'table'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DETableTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISTableTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'table', u'dbasetable', u'textfile', u'shapefile', u'featureclass',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
class ArcGISTableViewTypeMetadata(ArcGISTableTypeMetadata):
def __init__(self,
typeDisplayName=_(u'table or table view'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPTableViewTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISTableViewTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISTableViewTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table or table view'))
class ArcGISFieldTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedFieldTypes=None,
typeDisplayName=_(u'field'),
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.FieldTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedFieldTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedFieldTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedFieldTypes, types.TupleType):
allowedFieldTypes = list(allowedFieldTypes)
if allowedFieldTypes is not None:
for s in allowedFieldTypes:
assert isinstance(s, types.UnicodeType), u'allowedFieldTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedFieldTypes = map(unicode.strip, map(unicode.lower,
allowedFieldTypes))
else:
self._AllowedFieldTypes = None
super(ArcGISFieldTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=False,
canBeRelativePath=False,
basePathArgument=None,
useArcGISWorkspace=False,
normalizePath=False,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=False,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedFieldTypes(self):
return self._AllowedFieldTypes
AllowedFieldTypes = property(_GetAllowedFieldTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISFieldTypeMetadata, self).AppendXMLNodes(node, document)
allowedFieldTypesNode =
node.appendChild(document.createElement(u'AllowedFieldTypes'))
if self.AllowedFieldTypes is not None:
listNode =
allowedFieldTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedFieldTypes)):
self.AppendXMLNodesForValue(self.AllowedFieldTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISFieldTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedFieldTypes is not None and
methodLocals is not None and argMetadata.ArcGISParameterDependencies is not
None and len(argMetadata.ArcGISParameterDependencies) > 0 and
methodLocals[argMetadata.ArcGISParameterDependencies[0]] is not None:
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
fieldDataType =
conn.GetFieldDataType(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value)
if fieldDataType is not None and fieldDataType.lower() not in
self.AllowedFieldTypes:
if len(self.AllowedFieldTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the data type \'%(dt)s\', but this
function requires a %(type)s with the data type \'%(allowed)s\'. Please
provide a %(type)s with data type \'%(allowed)s\'.') % {u'type' :
self.TypeDisplayName, u'value' :
os.path.join(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value), u'variable' : variableName, u'dt': fieldDataType, u'allowed':
self.AllowedFieldTypes[0]}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the data type \'%(dt)s\', but this
function requires a %(type)s with one of the following data types:
\'%(allowed)s\'. Please provide a %(type)s with an allowed data type.') %
{u'type' : self.TypeDisplayName, u'value' :
os.path.join(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value), u'variable' : variableName, u'dt': fieldDataType, u'allowed':
unicode('\', \''.join(map(str, self.AllowedFieldTypes)))}))
return (valueChanged, value)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
assert methodLocals is not None and argMetadata is not None and
argMetadata.ArcGISParameterDependencies is not None and
len(argMetadata.ArcGISParameterDependencies) == 1,
u'ArcGISFieldTypeMetadata.Exists requires that methodLocals and argMetadata
be provided, and that argMetadata.ArcGISParameterDependencies[0] be set to
the parameter that specifies the field\'s table.'
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
exists =
conn.FieldExists(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
name)
return exists, exists
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
assert methodLocals is not None and argMetadata is not None and
argMetadata.ArcGISParameterDependencies is not None and
len(argMetadata.ArcGISParameterDependencies) == 1,
u'ArcGISFieldTypeMetadata.Delete requires that methodLocals and argMetadata
be provided, and that argMetadata.ArcGISParameterDependencies[0] be set to
the parameter that specifies the field\'s table.'
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
conn.DeleteField(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
_RaiseException(NotImplementedError(u'ArcGISFieldTypeMetadata.Copy is
not implemented.'))
class CoordinateSystemTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(CoordinateSystemTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPCoordinateSystemTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class EnvelopeTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(EnvelopeTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=u'([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)',
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPEnvelopeTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
@classmethod
def ParseCoordinatesFromString(cls, value):
if value is None:
return None, None, None, None
assert isinstance(value, basestring), u'value must be a string, or
None'
coords = value.split()
return float(coords[0]), float(coords[1]), float(coords[2]),
float(coords[3]) # left, bottom, right, top
class LinearUnitTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(LinearUnitTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPLinearUnitTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class MapAlgebraExpressionTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(MapAlgebraExpressionTypeMetadata, self).__init__(minLength=1,
maxLength=4000,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.SpatialAnalystUI.GPSAMapAlgebraExpTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.SpatialAnalystUI',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class PointTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(PointTypeMetadata, self).__init__(minLength=1,
mustMatchRegEx=u'([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)',
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPPointTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
@classmethod
def ParseCoordinatesFromString(cls, value):
if value is None:
return None, None
assert isinstance(value, basestring), u'value must be a string, or
None'
coords = value.split()
return float(coords[0]), float(coords[1])
class SpatialReferenceTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(SpatialReferenceTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPSpatialReferenceTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
from GeoEco.ArcGIS import _ArcGISObjectWrapper
if isinstance(value, _ArcGISObjectWrapper):
return False, value
(valueChanged, value) = super(SpatialReferenceTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
return (valueChanged, value)
class SQLWhereClauseTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(SQLWhereClauseTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPSQLExpressionTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
# NumPy and SciPy types
#
# Note: do not move import statements out of the functions to the module
level.
# We cannot require NumPy and SciPy to be installed just to import this
module.
class NumPyArrayTypeMetadata(TypeMetadata):
def __init__(self,
dimensions=None,
minShape=None,
maxShape=None,
allowedDTypes=None,
canBeNone=False):
assert isinstance(dimensions, (types.IntType, types.NoneType)),
u'dimensions must be an integer, or None'
assert dimensions is None or dimensions > 0, u'dimensions, if
provided, must be greater than zero'
assert isinstance(minShape, (types.NoneType, types.ListType,
types.TupleType)), u'minShape must be a list or tuple of integers, or None'
if isinstance(minShape, types.TupleType):
minShape = list(minShape)
assert minShape is None or dimensions is not None and len(minShape)
== dimensions, u'If minShape is provided, dimensions must also be provided,
and len(minShape) must equal dimensions'
if minShape is not None:
for value in minShape:
assert isinstance(value, types.IntType) and value >= 0, u'All
elements of minShape must be non-negative integers.'
assert isinstance(maxShape, (types.NoneType, types.ListType,
types.TupleType)), u'maxShape must be a list or tuple of integers, or None'
if isinstance(maxShape, types.TupleType):
maxShape = list(maxShape)
assert maxShape is None or dimensions is not None and len(maxShape)
== dimensions, u'If maxShape is provided, dimensions must also be provided,
and len(maxShape) must equal dimensions'
if maxShape is not None:
for value in maxShape:
assert isinstance(value, types.IntType) and value >= 0, u'All
elements of maxShape must be non-negative integers.'
assert isinstance(allowedDTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedDTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedDTypes, types.TupleType):
allowedDTypes = list(allowedDTypes)
if allowedDTypes is not None:
for value in allowedDTypes:
assert isinstance(value, types.UnicodeType) and len(value) >=
0, u'All elements of allowedDTypes must be non-empty Unicode strings.'
# We cannot assume that numpy can be imported. We must allow
instances of
# this class to be constructed without failing when numpy is not
# installed. But if numpy is installed, we initialize our pythonType
to
# the appropriate class.
try:
import numpy
pythonType = numpy.ndarray
except:
pythonType = object
super(NumPyArrayTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone)
self._Dimensions = dimensions
self._MinShape = minShape
self._MaxShape = maxShape
self._AllowedDTypes = allowedDTypes
def _GetDimensions(self):
return self._Dimensions
Dimensions = property(_GetDimensions, doc=DynamicDocString())
def _GetMinShape(self):
return self._MinShape
MinShape = property(_GetMinShape, doc=DynamicDocString())
def _GetMaxShape(self):
return self._MaxShape
MaxShape = property(_GetMaxShape, doc=DynamicDocString())
def _GetAllowedDTypes(self):
return self._AllowedDTypes
AllowedDTypes = property(_GetAllowedDTypes, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(NumPyArrayTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'Dimensions', node, document)
minShapeNode = node.appendChild(document.createElement(u'MinShape'))
if self.MinShape is not None:
listNode =
minShapeNode.appendChild(document.createElement(u'ArrayList'))
for value in self.MinShape:
listNode.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
maxShapeNode = node.appendChild(document.createElement(u'MaxShape'))
if self.MaxShape is not None:
listNode =
maxShapeNode.appendChild(document.createElement(u'ArrayList'))
for value in self.MaxShape:
listNode.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
allowedDTypesNode =
node.appendChild(document.createElement(u'AllowedDTypes'))
if self.AllowedDTypes is not None:
listNode =
allowedDTypesNode.appendChild(document.createElement(u'ArrayList'))
for value in self.AllowedDTypes:
listNode.appendChild(document.createElement(u'string')).appendChild(document.createTextNode(value))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(NumPyArrayTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.Dimensions is not None:
if self.Dimensions != value.ndim:
_RaiseException(ValueError(_(u'The NumPy array provided
for the %(variable)s must have %(dim1)i dimensions. The array you provided
has %(dim2)i.') % {u'variable' : variableName, u'dim1' : self.Dimensions,
u'dim2' : value.ndim}))
if self.MinShape is not None:
for i in range(self.Dimensions):
if value.shape[i] < self.MinShape[i]:
_RaiseException(ValueError(_(u'The NumPy array
provided for the %(variable)s must have the minimum dimensions %(dim1)i. The
array you provided has the dimensions %(dim2)i.') % {u'variable' :
variableName, u'dim1' : repr(self.MinShape), u'dim2' :
repr(list(value.shape))}))
if self.MaxShape is not None:
for i in range(self.Dimensions):
if value.shape[i] > self.MaxShape[i]:
_RaiseException(ValueError(_(u'The NumPy array
provided for the %(variable)s must have the maximum dimensions %(dim1)i. The
array you provided has the dimensions %(dim2)i.') % {u'variable' :
variableName, u'dim1' : repr(self.MaxShape), u'dim2' :
repr(list(value.shape))}))
if self.AllowedDTypes is not None and unicode(value.dtype.name)
not in self.AllowedDTypes:
_RaiseException(ValueError(_(u'The NumPy array provided for
the %(variable)s must have one of the following dtypes: %(types)s. The array
you provided has the dtype %(type)s.') % {u'variable' : variableName,
u'types' : repr(self.AllowedDTypes), u'type' : unicode(value.dtype.name)}))
return (valueChanged, value)
###############################################################################
# Names exported by this module
###############################################################################
__all__ = ['AnyObjectTypeMetadata',
'NoneTypeMetadata',
'ClassTypeMetadata',
'ClassInstanceTypeMetadata',
'ClassOrClassInstanceTypeMetadata',
'BooleanTypeMetadata',
'DateTimeTypeMetadata',
'FloatTypeMetadata',
'IntegerTypeMetadata',
'UnicodeStringTypeMetadata',
'SequenceTypeMetadata',
'ListTypeMetadata',
'TupleTypeMetadata',
'DictionaryTypeMetadata',
'StoredObjectTypeMetadata',
'FileTypeMetadata',
'TextFileTypeMetadata',
'DirectoryTypeMetadata',
'ArcGISGeoDatasetTypeMetadata',
'ArcGISRasterTypeMetadata',
'ArcGISRasterLayerTypeMetadata',
'ArcGISFeatureClassTypeMetadata',
'ArcGISFeatureLayerTypeMetadata',
'ShapefileTypeMetadata',
'ArcGISWorkspaceTypeMetadata',
'ArcGISTableTypeMetadata',
'ArcGISTableViewTypeMetadata',
'ArcGISFieldTypeMetadata',
'CoordinateSystemTypeMetadata',
'EnvelopeTypeMetadata',
'LinearUnitTypeMetadata',
'MapAlgebraExpressionTypeMetadata',
'PointTypeMetadata',
'SpatialReferenceTypeMetadata',
'SQLWhereClauseTypeMetadata',
'NumPyArrayTypeMetadata']
Thanks for your interest in MGET. I'm sorry the sampling tool is not working
for you. The short answer is that the tool does not currently support
sampling raster bands, only rasters or raster layers. But I have a solution
for you.
First, here is some code that demonstrates how to sample rasters that do not
have bands from a traditional Python geoprocessing script:
# Instantiate Arc 9.2 geoprocessor.
import arcgisscripting
gp = arcgisscripting.create()
# Reference MGET toolbox. Note: path may change before MGET 0.7 is
# released. See https://code.env.duke.edu/projects/mget/ticket/299
gp.AddToolbox(r'C:\Python24\Lib\site-packages\GeoEco\ArcGISToolbox\Marine
Geospatial Ecology Tools.tbx')
# A simple sampling example for two fields:
points = r'C:\HabModExample2\Geodatabase.mdb\PointsToSample'
rasters = r'C:\HabModExample2\OceanographyRasters\Chl\Monthly\chl199908;' + \
r'C:\HabModExample2\OceanographyRasters\SST\Monthly\sst\sst199908'
fields = 'Chlorophyll;SST'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
# Since we are sampling Chl and SST for August 1998, we can restrict
# the sampler to just do the points that have that date. Since we're
# querying an MS Access database, we can use VBScript DatePart
# function. This is not very efficient, but will work.
where = 'DatePart("m", [obs_date]) = 8'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields, where)
# If the destination field has the an integer data type (i.e. SHORT or
# LONG), we must explicitly cast the sampled values to integers. This
# is because the MGET tool always gets floats back from ArcGIS, even
# when sampling integer rasters. A future version of the MGET tool
# will do this automatically, or call ArcGIS in a different way, so
# this is not required. Sorry for the inconvenience.
fields = 'Bathymetry'
rasters = r'C:\HabModExample2\OceanographyRasters\Bathymetry\etopo2v2'
expressions = 'int(value)' # etopo2v2 is depth as integer
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields, where,
'#', '#', expressions)
I saved that script to C:\SampTest\SampTest.py. It uses points and rasters
from the HabModExample2 habitat modeling example on the MGET web site. I ran
it on an Arc 9.2 SP6 machine and got the following output. You'll see the
output if you run it from a CMD shell, but if you run it from a Python
debugger (e.g. PythonWin) I don’t think you'll see it because those debuggers
do not traditionally capture messages written to the stdout stream.
C:\SampTest>SampTest.py
2008-12-11 21:03:29,246 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Chl\\Monthly\\chl199908',
u'C:\\HabModExample2\\OceanographyRasters\\SST\\Monthly\\sst\\sst199908'],
fields=[u'Chlorophyll', u'SST']...
2008-12-11 21:03:47,763 INFO Sampled 2 rasters at 600 points.
2008-12-11 21:04:06,226 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Chl\\Monthly\\chl199908',
u'C:\\HabModExample2\\OceanographyRasters\\SST\\Monthly\\sst\\sst199908'],
fields=[u'Chlorophyll', u'SST'], where=DatePart("m", [obs_date]) = 8...
2008-12-11 21:04:23,822 INFO Sampled 2 rasters at 328 points.
2008-12-11 21:04:40,775 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\HabModExample2\\OceanographyRasters\\Bathymetry\\etopo2v2'],
fields=[u'Bathymetry'], where=DatePart("m", [obs_date]) = 8...
2008-12-11 21:04:58,901 INFO Sampled 1 rasters at 328 points.
Here is what code for sampling bands should look like:
# Create a raster with two bands so we can test band sampling.
bands = r'C:\HabModExample2\OceanographyRasters\Chl\Monthly\chl199908;' + \
r'C:\HabModExample2\OceanographyRasters\SST\Monthly\sst\sst199908'
gp.OverwriteOutput = True
gp.CompositeBands_management(bands, r'C:\SampTest\multiband.img')
# Sample the bands.
rasters = r'C:\SampTest\multiband.img\Band_1;' + \
r'C:\SampTest\multiband.img\Band_2'
fields = 'Chlorophyll;SST'
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
But the tool fails with this message:
C:\SampTest>SampTest.py
2008-12-11 21:13:36,144 ERROR ValueError: The value specified for the element
0 of the rasters parameter (where 0 is the first element),
C:\SampTest\multiband.img\Band_1, exists but it is not a raster or raster
layer. Please specify a raster or raster layer.
Traceback (most recent call last):
File "C:\SampTest\SampTest.py", line 56, in ?
gp.ArcGISRasterSamplerSampleRasters_GeoEco(points, rasters, fields)
RuntimeError:
ValueError: The value specified for the element 0 of the rasters parameter
(where 0 is the first element), C:\SampTest\multiband.img\Band_1, exists but
it is not a raster or raster layer. Please specify a raster or raster layer.
Error in script ArcGISRasterSamplerSampleRasters.
Error in executing: cmd.exe /C
C:\Python24\Lib\SITE-P~1\GeoEco\ARCGIS~1\Scripts\AR87D7~1.PY
"C:\HabModExample2\Geodatabase.mdb\PointsToSample"
"C:\SampTest\multiband.img\Band_1;C:\SampTest\multiband.img\Band_2"
"Chlorophyll;SST" "#" "NEAREST" "#" "#" "#"
"C:\HabModExample2\Geodatabase.mdb\PointsToSample"
Failed to execute (ArcGISRasterSamplerSampleRasters).
If you are not seeing anything like that, then there is some other problem.
If you're trying to run it from PythonWin, IDLE, or another editor, try it
from a CMD shell instead. If you still don't see any messages, it probably
means there is an installation problem. Usually it means the pywin32 Python
package is not installed. You could check for that (see MGET's Installation
Instructions).
Now, assuming you can reproduce an error that looks like the above (i.e.
"ValueError: The value specified ... exists but it is not a raster or raster
layer.") you can fix it by overwriting your file
C:\Python24\Lib\site-packages\GeoEco\Types.py with the one attached to this
message. This contains a one line fix that enables the tool to sample bands.
My apologies for the bug. You should then get this output:
C:\SampTest>SampTest.py
2008-12-11 21:18:13,516 INFO Sampling rasters:
points=C:\HabModExample2\Geodatabase.mdb\PointsToSample,
rasters=[u'C:\\SampTest\\multiband.img\\Band_1',
u'C:\\SampTest\\multiband.img\\Band_2'], fields=[u'Chlorophyll', u'SST']...
2008-12-11 21:18:35,184 INFO Sampled 2 rasters at 600 points.
Hope that helps. Let me know if it does not...
Jason
-----Original Message-----
From:
[mailto:]
Sent: Thursday, December 11, 2008 7:55 PM
To:
Subject: ArcGISRasterSamplerSampleRasters
Hi MGET-ers.
I'm new to the list and new to the GeoEco toolbox, so here goes...
I'm trying to sample all the rasters (including multiple raster bands) in a
directory using the ArcGISRasterSamplerSampleRasters tool. All the rasters are
Erdas IMAGEs (.img), 7 are single-band, 3 are 3-band, and 3 are 6-band images,
for a total of 34 fields being added to my point shapefile.
I originally downloaded the toolbox because I had previously tried Python to
use the "Sample" command and also to loop through "Extract Values to Points",
but ran into errors in both. (The former would not allow that many rasters to
be sampled, and the latter just failed at various places, giving the "ERROR
99999: unknown error" message.)
So, can the ArcGISRasterSamplerSampleRasters tool sample all bands of
multi-band rasters, or do I need to copy each band as a single-band raster?
I'm
running the tool unsuccessfully in a Python script now, but I get no error
messages when it fails, so I'm guessing that this is the problem. Here's the
pseudocode of what I'm doing:
rasters = 'raster1.img;raster2.img\Band_1;raster2.img\Band_2...'
fields = 'raster1;raster2_1;raster2_2...'
gp.ArcGISRasterSamplerSampleRasters(shapefile, rasters, fields)
Thanks,
Joe
# Types.py - Provides classes derived from GeoEco.Metadata.TypeMetadata that
# represent data types of properties and method arguments and return values
for
# classes in the GeoEco Python package.
#
# Copyright (C) 2007 Jason J. Roberts
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License (available in the file LICENSE.TXT)
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
import datetime
import inspect
import operator
import os.path
import re
import sys
import time
import types
import xml.dom
from GeoEco.DynamicDocString import DynamicDocString
from GeoEco.Internationalization import _
from GeoEco.Metadata import Metadata, TypeMetadata
# Private helper function for raising exceptions
def _RaiseException(e):
from GeoEco.Logging import Logger
Logger.RaiseException(e)
# Types representing Python class instances or classes
class AnyObjectTypeMetadata(TypeMetadata):
def __init__(self, canBeNone=False):
super(AnyObjectTypeMetadata,
self).__init__(pythonType=types.ObjectType,
canBeNone=canBeNone,
comIDLType=u'VARIANT',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class NoneTypeMetadata(TypeMetadata):
def __init__(self):
super(NoneTypeMetadata, self).__init__(pythonType=types.NoneType,
canBeNone=True)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is not None:
_RaiseException(TypeError(_(u'The %s must be None (also called
null or empty in languages other than Python).') % variableName))
return (False, value)
class ClassTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassTypeMetadata, self).__init__(pythonType=cls,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is None:
if not self.CanBeNone:
_RaiseException(TypeError(_(u'The %s is required. Please
provide a value.') % variableName))
elif not issubclass(value, self.PythonType):
_RaiseException(TypeError(_(u'The value provided for the
%(variable)s is invalid because it is a %(type)s, an invalid type. Please
provide the class %(class)s or a subclass.') % {u'variable' : variableName,
u'type' : type(value).__name__, u'class' : self.PythonType.__name__}))
return (False, value)
class ClassInstanceTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassInstanceTypeMetadata, self).__init__(pythonType=cls,
canBeNone=canBeNone)
class ClassOrClassInstanceTypeMetadata(TypeMetadata):
def __init__(self, cls, canBeNone=False):
assert inspect.isclass(cls), u'cls must be a class'
super(ClassOrClassInstanceTypeMetadata,
self).__init__(pythonType=cls, canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
if value is None:
if not self.CanBeNone:
_RaiseException(TypeError(_(u'The %s is required. Please
provide a value.') % variableName))
elif not (inspect.isclass(value) and issubclass(value,
self.PythonType)) and not isinstance(value, self.PythonType):
_RaiseException(TypeError(_(u'The value provided for the
%(variable)s is invalid because it is a %(type)s, an invalid type. Please
provide the class %(class)s, a subclass, or an instance of it or a
subclass.') % {u'variable' : variableName, u'type' : type(value).__name__,
u'class' : self.PythonType.__name__}))
return (False, value)
# Simple Python types from which many other types derive
class BooleanTypeMetadata(TypeMetadata):
def __init__(self,
canBeNone=False,
allowedValues=None):
super(BooleanTypeMetadata,
self).__init__(pythonType=types.BooleanType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'VARIANT_BOOL',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPBooleanTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'boolean')).appendChild(document.createTextNode(unicode(value).lower()))
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.BooleanType), u'value must be a
boolean'
if value:
return '-1' # VARIANT_TRUE
return '0' # VARIANT_FALSE
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(BooleanTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip().lower()
if s == u'true':
return True
if s == u'false':
return False
_RaiseException(ValueError(_(u'Failed to parse a boolean from the
string "%(string)s" provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). Please provide either "True" or "False".') %
{u'string' : s, u'paramName' : paramDisplayName, u'paramIndex' : paramIndex}))
class DateTimeTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (datetime.datetime, types.NoneType)),
u'minValue must be a datetime.datetime, or None'
assert isinstance(maxValue, (datetime.datetime, types.NoneType)),
u'maxValue must be a datetime.datetime, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(DateTimeTypeMetadata,
self).__init__(pythonType=datetime.datetime,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'DATE',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPDateTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(DateTimeTypeMetadata, self).AppendXMLNodes(node, document)
#Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
#Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
_RaiseException(NotImplementedError(_(u'Properties or method
parameters of type DateTimeTypeMetadata cannot currently have default
values.')))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if value is not None and not isinstance(value, datetime.datetime):
try:
import pythoncom
except:
pass
else:
if isinstance(value, pythoncom.PyTimeType):
value = datetime.datetime(value.year, value.month,
value.day, value.hour, value.minute, value.second, value.msec)
valueChanged = True
(valueChanged2, value) = super(DateTimeTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)s provided
for the %(variable)s is less than the minimum allowed value %(minValue)s.') %
{u'value' : unicode(value), u'variable' : variableName, u'minValue' :
unicode(self.MinValue)}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)s provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)s.') % {u'value' : unicode(value), u'variable' : variableName,
u'maxValue' : unicode(self.MaxValue)}))
return (valueChanged or valueChanged2, value)
def COMIDLRepresentationOfValue(self, value):
_RaiseException(NotImplementedError(_(u'Properties or method
parameters of type DateTimeTypeMetadata cannot currently have default
values.')))
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(DateTimeTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip().lower()
# Sadly, it appears that ArcGIS passes datetimes in the
locale-specific
# format. I verified this on Windows by switching the Regional and
# Language Options from English (United States) to German (Germany)
and
# observing the datetime string being passed in a different format.
#
# This means we have to try to parse the string in the locale-specific
# format. Sadly Python does not give us much help here. The
# time.strptime function does have some support for parsing
# locale-specific formats (%x and %X) but it does not seem to work on
# Windows (ArcGIS passes dates as mm/dd/YYYY but the function expects
# mm/dd/yy). As a result, we have to exhaustively try to parse
different
# formats. This is really annoying. We could take a dependency on
# mxDateTime but their licensing model is not compatible with ours,
and
# it would be a shame to take the dependency just to parse a datetime.
t = self.ParseDatetimeFromString(s)
if t is None:
_RaiseException(ValueError(_(u'Failed to parse a date/time value
from the string "%(string)s" provided for the %(paramName)s parameter
(parameter number %(paramIndex)i). Please provide a value in a supported
date/time format. If you provide a date but omit the time, midnight is
assumed. You may not provide a time without a date.') % {u'string' : s,
u'paramName' : paramDisplayName, u'paramIndex' : paramIndex}))
return t
@classmethod
def ParseDatetimeFromString(cls, s):
# Order the parsing formats that we will attempt according to whether
# the year, month, or day comes first in the current locale-specific
# date format.
yearFirstFormats = ['%Y/%m/%d',
'%Y-%m-%d',
'%Y-.%m-.%d',
'%y/%m/%d',
'%y-%m-%d',
'%y-.%m-.%d',
'%Y/%m/%d %I:%M:%S %p',
'%Y-%m-%d %I:%M:%S %p',
'%Y.%m.%d %I:%M:%S %p',
'%y/%m/%d %I:%M:%S %p',
'%y-%m-%d %I:%M:%S %p',
'%y.%m.%d %I:%M:%S %p',
'%Y/%m/%d %H:%M:%S',
'%Y-%m-%d %H:%M:%S',
'%Y.%m.%d %H:%M:%S',
'%y/%m/%d %H:%M:%S',
'%y-%m-%d %H:%M:%S',
'%y.%m.%d %H:%M:%S']
dayFirstFormats = ['%d/%m/%Y',
'%d-%m-%Y',
'%d.%m.%Y',
'%d/%m/%y',
'%d-%m-%y',
'%d.%m.%y',
'%d/%m/%Y %I:%M:%S %p',
'%d-%m-%Y %I:%M:%S %p',
'%d.%m.%Y %I:%M:%S %p',
'%d/%m/%y %I:%M:%S %p',
'%d-%m-%y %I:%M:%S %p',
'%d.%m.%y %I:%M:%S %p',
'%d/%m/%Y %H:%M:%S',
'%d-%m-%Y %H:%M:%S',
'%d.%m.%Y %H:%M:%S',
'%d/%m/%y %H:%M:%S',
'%d-%m-%y %H:%M:%S',
'%d.%m.%y %H:%M:%S']
monthFirstFormats = ['%m/%d/%Y',
'%m-%d-%Y',
'%m.%d.%Y',
'%m/%d/%y',
'%m-%d-%y',
'%m.%d.%y',
'%m/%d/%Y %I:%M:%S %p',
'%m-%d-%Y %I:%M:%S %p',
'%m.%d.%Y %I:%M:%S %p',
'%m/%d/%y %I:%M:%S %p',
'%m-%d-%y %I:%M:%S %p',
'%m.%d.%y %I:%M:%S %p',
'%m/%d/%Y %H:%M:%S',
'%m-%d-%Y %H:%M:%S',
'%m.%d.%Y %H:%M:%S',
'%m/%d/%y %H:%M:%S',
'%m-%d-%y %H:%M:%S',
'%m.%d.%y %H:%M:%S']
otherFormats = ['%Y.%m.%d.',
'%Y.%m.%d. %H:%M:%S',
'%Y-%m-%d %I:%M:%S.%p',
'%d/%m %Y',
'%d/%m %Y %H:%M:%S']
localeTimeStr = time.strftime('%x', (2007, 12, 31, 0, 0, 0, 0, 365,
-1))
if localeTimeStr.startswith('2007') or localeTimeStr.startswith('07')
or localeTimeStr.startswith('7'):
formats = yearFirstFormats + dayFirstFormats + monthFirstFormats
+ otherFormats
elif localeTimeStr.startswith('31'):
formats = dayFirstFormats + monthFirstFormats + yearFirstFormats
+ otherFormats
else:
formats = monthFirstFormats + yearFirstFormats + dayFirstFormats
+ otherFormats
# Parse the string using the list of formats.
t = None
for f in formats:
try:
t = time.strptime(s, f)
except:
pass
else:
break
if t is not None:
return datetime.datetime(*t[0:6])
return None
class FloatTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (types.FloatType, types.NoneType)),
u'minValue must be a float, or None'
assert isinstance(maxValue, (types.FloatType, types.NoneType)),
u'maxValue must be a float, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(FloatTypeMetadata, self).__init__(pythonType=types.FloatType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'double',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPDoubleTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(FloatTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'double')).appendChild(document.createTextNode(unicode(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if isinstance(value, types.IntType):
value = float(value)
valueChanged = True
(valueChanged2, value) = super(FloatTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)G provided
for the %(variable)s is less than the minimum allowed value %(minValue)G.') %
{u'value' : value, u'variable' : variableName, u'minValue' : self.MinValue}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)G provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)G.') % {u'value' : value, u'variable' : variableName, u'maxValue'
: self.MaxValue}))
return (valueChanged or valueChanged2, value)
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.FloatType), u'value must be a float'
return str(value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(FloatTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip()
try:
value = float(s)
except Exception, e:
_RaiseException(ValueError(_(u'Failed to parse a floating-point
number from the string "%(string)s" provided for the %(paramName)s parameter
(parameter number %(paramIndex)i). Please provide a string with valid
formatting. The Python float function reported: %(msg)s') % {u'string' : s,
u'paramName' : paramDisplayName, u'paramIndex' : paramIndex, u'msg' :
unicode(e)}))
return value
class IntegerTypeMetadata(TypeMetadata):
def __init__(self,
minValue=None,
maxValue=None,
canBeNone=False,
allowedValues=None):
assert isinstance(minValue, (types.IntType, types.NoneType)),
u'minValue must be an integer, or None'
assert isinstance(maxValue, (types.IntType, types.NoneType)),
u'maxValue must be an integer, or None'
assert minValue is None or maxValue is None or minValue <= maxValue,
u'minValue must be less than or equal to maxValue'
super(IntegerTypeMetadata, self).__init__(pythonType=types.IntType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'long',
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPLongTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
self._MinValue = minValue
self._MaxValue = maxValue
def _GetMinValue(self):
return self._MinValue
MinValue = property(_GetMinValue, doc=DynamicDocString())
def _GetMaxValue(self):
return self._MaxValue
MaxValue = property(_GetMaxValue, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(IntegerTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MinValue', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxValue', node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(IntegerTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.MinValue is not None and value < self.MinValue:
_RaiseException(ValueError(_(u'The value %(value)i provided
for the %(variable)s is less than the minimum allowed value %(minValue)i.') %
{u'value' : value, u'variable' : variableName, u'minValue' : self.MinValue}))
if self.MaxValue is not None and value > self.MaxValue:
_RaiseException(ValueError(_(u'The value %(value)i provided
for the %(variable)s is greater than the maximum allowed value
%(maxValue)i.') % {u'value' : value, u'variable' : variableName, u'maxValue'
: self.MaxValue}))
return (valueChanged, value)
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.IntType), u'value must be an int'
return str(value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
s = super(IntegerTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex).strip()
try:
value = int(s)
except Exception, e:
_RaiseException(ValueError(_(u'Failed to parse an integer from
the string "%(string)s" provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). Please provide a string with valid formatting. The
Python integer function reported: %(msg)s') % {u'string' : s, u'paramName' :
paramDisplayName, u'paramIndex' : paramIndex, u'msg' : unicode(e)}))
return value
class UnicodeStringTypeMetadata(TypeMetadata):
def __init__(self,
stripWhitespace=True,
makeLowercase=False,
minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=False,
allowedValues=None,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPStringTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(stripWhitespace, types.BooleanType),
u'stripWhitespace must be a boolean'
assert isinstance(makeLowercase, types.BooleanType), u'makeLowercase
must be a boolean'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
assert isinstance(mustMatchRegEx, (types.NoneType,
types.UnicodeType)), u'mustMatchRegEx must be a Unicode string, or None'
super(UnicodeStringTypeMetadata,
self).__init__(pythonType=types.UnicodeType,
canBeNone=canBeNone,
allowedValues=allowedValues,
comIDLType=u'BSTR',
canBeCOMParameter=True,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._StripWhitespace = stripWhitespace
self._MakeLowercase = makeLowercase
self._MinLength = minLength
self._MaxLength = maxLength
self._MustMatchRegEx = mustMatchRegEx
def _GetStripWhitespace(self):
return self._StripWhitespace
StripWhitespace = property(_GetStripWhitespace, doc=DynamicDocString())
def _GetMakeLowercase(self):
return self._MakeLowercase
MakeLowercase = property(_GetMakeLowercase, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def _GetMustMatchRegEx(self):
return self._MustMatchRegEx
MustMatchRegEx = property(_GetMustMatchRegEx, doc=DynamicDocString())
def COMIDLRepresentationOfValue(self, value):
assert isinstance(value, types.UnicodeType), u'value must be a
Unicode string'
return '"' + str(value).replace('"', '\\"') + '"'
def AppendXMLNodes(self, node, document):
super(UnicodeStringTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'StripWhitespace', node,
document)
Metadata.AppendPropertyXMLNode(self, u'MakeLowercase', node, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MustMatchRegEx', node,
document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
node.appendChild(document.createElement(u'string')).appendChild(document.createTextNode(value))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
valueChanged = False
if isinstance(value, types.StringType):
value = unicode(value)
valueChanged = True
(valueChanged2, value) = super(UnicodeStringTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
valueChanged = valueChanged or valueChanged2
if value is not None:
if self.StripWhitespace:
value = value.strip()
valueChanged = True
if self.MakeLowercase:
value = value.lower()
valueChanged = True
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is too short. It may be no shorter than %(len)i characters.') %
{u'variable' : variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is too long. It may be no longer than %(len)i characters.') %
{u'variable' : variableName, u'len' : self.MaxLength}))
if self.MustMatchRegEx is not None and not
re.match(self.MustMatchRegEx, value):
_RaiseException(ValueError(_(u'The value provided for the
%(variable)s is not formatted properly. Please check the documentation for
the %(variable)s for details on the format. (Technical details: the value did
not match the regular expression "%(regex)s".)') % {u'variable' :
variableName, u'regex' : self.MustMatchRegEx}))
return (valueChanged, value)
# Python sequence types
class SequenceTypeMetadata(TypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
pythonType=types.ObjectType,
canBeNone=False,
comIDLType=None,
canBeCOMParameter=True,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=False):
assert isinstance(elementType, TypeMetadata), u'elementType must be
an instance of TypeMetadata'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
assert isinstance(maxItemsToValidate, types.IntType) and
maxItemsToValidate >= 0, u'maxItemsToValidate must be an integer greater than
or equal to 0'
assert isinstance(mustBeSameLengthAsArgument, (types.UnicodeType,
types.NoneType)), u'mustBeSameLengthAsArgument must be a Unicode string, or
None'
assert not canBeArcGISInputParameter or not arcGISType !=
u'ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass' or
(issubclass(elementType.PythonType, basestring) or not
hasattr(elementType.PythonType, '__getitem__')), u'For this sequence type to
be passed as an ArcGIS input parameter using the ArcGIS data type
ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass, its elements may not
themselves be sequences unless they are strings. (In other words, you can\'t
pass nested sequences using ESRI.ArcGIS.Geoprocessing.GPMultiValueTypeClass.)'
# If comIDLType is None and canBeCOMParameter is True, which is
# the normal situation, set comIDLType to a SAFEARRAY of the proper
IDL
# type for the elementType.
if comIDLType is None and canBeCOMParameter:
t = elementType
while isinstance(t, SequenceTypeMetadata):
t = t.ElementType
comIDLType = u'SAFEARRAY(%s)' % t.COMIDLType
# Initialize the base class.
super(SequenceTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone,
comIDLType=comIDLType,
canBeCOMParameter=canBeCOMParameter,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._ElementType = elementType
self._MinLength = minLength
self._MaxLength = maxLength
self._MaxItemsToValidate = maxItemsToValidate
self._MustBeSameLengthAsArgument = mustBeSameLengthAsArgument
def _GetElementType(self):
return self._ElementType
ElementType = property(_GetElementType, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def _GetMaxItemsToValidate(self):
return self._MaxItemsToValidate
MaxItemsToValidate = property(_GetMaxItemsToValidate,
doc=DynamicDocString())
def _GetMustBeSameLengthAsArgument(self):
return self._MustBeSameLengthAsArgument
MustBeSameLengthAsArgument = property(_GetMustBeSameLengthAsArgument,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(SequenceTypeMetadata, self).AppendXMLNodes(node, document)
elementTypeNode =
node.appendChild(document.createElement(u'ElementTypeMetadata'))
self.ElementType.AppendXMLNodes(elementTypeNode, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxItemsToValidate', node,
document)
Metadata.AppendPropertyXMLNode(self, u'MustBeSameLengthAsArgument',
node, document)
def AppendXMLNodesForValue(self, value, node, document):
assert isinstance(value, self.PythonType), u'value must be an
instance of %s' % self.PythonType.__name__
assert isinstance(node, xml.dom.Node) and node.nodeType ==
xml.dom.Node.ELEMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==ELEMENT_NODE'
assert isinstance(document, xml.dom.Node) and document.nodeType ==
xml.dom.Node.DOCUMENT_NODE, u'node must be an instance of xml.dom.Node with
nodeType==DOCUMENT_NODE'
listNode = node.appendChild(document.createElement(u'ArrayList'))
for element in value:
self.ElementType.AppendXMLNodesForValue(element, listNode,
document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(SequenceTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
length1 = 0
length2 = 0
if value is not None:
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too short. It must contain at least %(len)i items.') % {u'variable' :
variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too long. It must contain no more than %(len)i items.') % {u'variable' :
variableName, u'len' : self.MaxLength}))
if self.MustBeSameLengthAsArgument is not None and methodLocals
is not None:
assert methodLocals.has_key(self.MustBeSameLengthAsArgument),
_(u'To validate the %(param1)s of the method being validated, that method
must also have an parameter named %(param2)s.') % {u'param1' : variableName,
u'param2' : self.MustBeSameLengthAsArgument}
length1 = len(value)
if self.MustBeSameLengthAsArgument is not None and methodLocals
is not None and methodLocals[self.MustBeSameLengthAsArgument] is not None:
try:
length2 =
len(methodLocals[self.MustBeSameLengthAsArgument])
except Exception, e:
_RaiseException(TypeError(_(u'To validate the %(param1)s
of the method being validated, the length of method\'s %(param2)s parameter
must be able to be obtained with the Python len function. That function
raised the following exception when passed the value of that parameter:
%(error)s: %(msg)s') % {u'param1' : variableName, u'param2' :
self.MustBeSameLengthAsArgument, u'error': e.__class__.__name__, u'msg':
unicode(e)}))
if length1 != length2:
_RaiseException(TypeError(_(u'The %(param1)s must have the
same number of items as the %(param2)s parameter.') % {u'param1' :
variableName, u'param2' : self.MustBeSameLengthAsArgument}))
return (valueChanged, value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
paramString = super(SequenceTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex)
# The input string is a list of values formatted as follows:
# - Values are separated by semicolons
# - If a value contains a space or tab it is enclosed in
apostrophes
# - There are no escape sequences for semicolons or apostrophes
# - An empty string is formatted as two successive semicolons
#
# We parse the string using a finite state machine. Because there are
no
# escape sequences for semicolons or apostrophes, it is not possible
for
# the user to pass certain strings to us, and some strings will lead
to
# undesirable results.
FIRST_CHARACTER = 1 # We are
positioned on the first character of the input strong or the first character
following the semicolon that terminated the previous element.
INSIDE_SEMICOLON = 2 # We are
positioned on the second or subsequent character inside an element that did
not begin with an apostrophe.
INSIDE_QUOTE_NO_SPACE_FOUND = 3 # We are
positioned on the second or subsequent character inside an element that began
with an apostrophe, and we have not yet found the space or tab character that
necessitated the apostrophe, so it could just be part of the string.
INSIDE_QUOTE_SPACE_FOUND = 4 # We are
positioned on the second or subsequent character inside an element that began
with an apostrophe, and we have already found the space or tab character that
necessitated the apostrophe.
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE = 5 # We are
positioned on a character following the second or subsequent apostrophe
inside an element that begain with an apostrophe and was found to have a
space or tab character. The apostrophe we just parsed could be the closing
apostrophe, if we now are positioned on a semicolon or the end of the string.
state = FIRST_CHARACTER
params = []
i = 0
paramStart = 0
paramCharCount = 0
failedBecauseArcGISForgotQuotes = False # Sometimes ArcGIS seems
to violate the rules described above in a way that makes the string
unparsable. In this case we treat it as a single string and report a warning.
#from GeoEco.Logging import Logger
try:
while i < len(paramString):
#Logger.Debug('----------------------------')
#Logger.Debug(u'i = %i, c = %s, state = %i, paramStart = %i,
paramCharCount= %i' % (i, paramString[i], state, paramStart, paramCharCount))
if state == FIRST_CHARACTER:
if paramString[i] == u';':
params.append(u'')
elif paramString[i] == u'\'':
state = INSIDE_QUOTE_NO_SPACE_FOUND
paramStart = i
paramCharCount = 1
else:
state = INSIDE_SEMICOLON
paramStart = i
paramCharCount = 1
elif state == INSIDE_SEMICOLON:
if paramString[i] == u' ' or paramString[i] == u'\t':
failedBecauseArcGISForgotQuotes = True
raise ValueError(_(u'Failed to parse a list of values
from the string provided for the %(paramName)s parameter (parameter number
%(paramIndex)i). The parser encountered an error: a space or tab character
was found outside of enclosing apostrophes. If an element in the list
contains a space or tab, enclose the entire element in apostrophes. If you
are invoking this function from ArcGIS, there is no need to do this
explicitly, ArcGIS does it for you; you must have received this error for a
different reason. Please contact the author of this function for
assistance.') % {u'paramName' : paramDisplayName, u'paramIndex' : paramIndex})
elif paramString[i] == u';':
state = FIRST_CHARACTER
params.append(paramString[paramStart:paramStart+paramCharCount])
else:
paramCharCount += 1
elif state == INSIDE_QUOTE_NO_SPACE_FOUND:
if paramString[i] == u';':
state = FIRST_CHARACTER
if paramString[paramStart:paramStart+paramCharCount]
== u'\'\'':
params.append(u'')
else:
params.append(paramString[paramStart:paramStart+paramCharCount])
elif paramString[i] == u' ' or paramString[i] == u'\t':
state = INSIDE_QUOTE_SPACE_FOUND
paramStart += 1
else:
paramCharCount += 1
elif state == INSIDE_QUOTE_SPACE_FOUND:
if paramString[i] == u'\'':
state =
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE
else:
paramCharCount += 1
elif state ==
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE:
if paramString[i] == u'\'':
paramCharCount += 1
elif paramString[i] == u';':
state = FIRST_CHARACTER
params.append(paramString[paramStart:paramStart+paramCharCount])
else:
paramCharCount += 1
else:
_RaiseException(RuntimeError(_(u'Failed to parse a list
of values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i) due to a programming error in the parser: the parser
was found to be in unknown state %(state)i. Please contact the author of this
function for assistance.') % {u'paramName' : paramDisplayName, u'paramIndex'
: paramIndex, u'state' : state}))
#Logger.Debug('state = %i, paramStart = %i, paramCharCount=
%i' % (state, paramStart, paramCharCount))
i += 1
except:
if failedBecauseArcGISForgotQuotes:
from GeoEco.Logging import Logger
Logger.Warning(_(u'The string provided for %(paramName)s
parameter (parameter number %(paramIndex)i) included a space but the string
itself was not enclosed in apostrophes. This is a known problem with how
ArcGIS passes parameters to Python scripts. As a result, the string cannot be
parsed into a list of items and will be treated as a single item. This may
result in unintended effects. Please check your outputs carefully.') %
{u'paramName' : paramDisplayName, u'paramIndex' : paramIndex})
params.append(paramString)
else:
raise
else:
if state == FIRST_CHARACTER:
if paramString.endswith(u';'):
params.append(u'')
elif state == INSIDE_SEMICOLON or state ==
INSIDE_QUOTE_NO_SPACE_FOUND or state ==
INSIDE_QUOTE_SPACE_FOUND_POSSIBLE_TRAILING_QUOTE:
params.append(paramString[paramStart:paramStart+paramCharCount])
elif state == INSIDE_QUOTE_SPACE_FOUND:
_RaiseException(ValueError(_(u'Failed to parse a list of
values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i). The parser encountered an error: the last element in
the list begain with an apostrophe, included at least one space or tab
character but did not end with an apostrophe. Please end your string with an
apostrophe. If you are invoking this function from ArcGIS, there is no need
to do this explicitly, ArcGIS does it for you; you must have received this
error for a different reason. Please contact the author of this function for
assistance.') % {u'paramName' : paramDisplayName, u'paramIndex' :
paramIndex}))
else:
_RaiseException(RuntimeError(_(u'Failed to parse a list of
values from the string provided for the %(paramName)s parameter (parameter
number %(paramIndex)i) due to a programming error in the parser: the parser
was found to be in unknown state %(state)i. Please contact the author of this
function for assistance.') % {u'paramName' : paramDisplayName, u'paramIndex'
: paramIndex, u'state' : state}))
# The parser built a list of Unicode strings. If we're supposed to
# return a list of Unicode strings, just return now.
if issubclass(self.ElementType.PythonType, types.UnicodeType):
return params
# Parse the list of Unicode strings into the appropriate Python type.
# For Python types that are not strings, we interpret whitespace as
# None.
values = []
for i in range(len(params)):
s = params[i]
if not issubclass(self.ElementType.PythonType, types.StringType):
s = params[i].strip()
if len(s) <= 0 and self.ElementType.CanBeNone:
values.append(None)
continue
values.append(self.ElementType.ParseValueFromArcGISInputParameterString(s,
_(u'element at position %i (where 0 is the first element) of the %s') % (i,
paramDisplayName), paramIndex))
return values
class ListTypeMetadata(SequenceTypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
canBeNone=False):
super(ListTypeMetadata, self).__init__(elementType=elementType,
minLength=minLength,
maxLength=maxLength,
maxItemsToValidate=maxItemsToValidate,
mustBeSameLengthAsArgument=mustBeSameLengthAsArgument,
pythonType=types.ListType,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ListTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
itemsToValidate = min(len(value), self.MaxItemsToValidate)
if itemsToValidate != len(value):
from GeoEco.Logging import Logger
Logger.Debug(_(u'The %(var)s contains %(count1)i items, but
to minimize execution time, only the first %(count2)i items will be
validated. If an invalid item is present, unexpected results may occur.') %
{u'var': variableName, u'count1': len(value), u'count2':
self.MaxItemsToValidate})
for i in range(itemsToValidate):
(elementValueChanged, newElementValue) =
self.ElementType.ValidateValue(value[i], _(u'element %i of the %s (where 0 is
the first element)') % (i, variableName), methodLocals, argMetadata)
if elementValueChanged:
value[i] = newElementValue
valueChanged = True
return (valueChanged, value)
class TupleTypeMetadata(SequenceTypeMetadata):
def __init__(self,
elementType,
minLength=0,
maxLength=2147483647,
maxItemsToValidate=2147483647,
mustBeSameLengthAsArgument=None,
canBeNone=False):
super(TupleTypeMetadata, self).__init__(elementType=elementType,
minLength=minLength,
maxLength=maxLength,
maxItemsToValidate=maxItemsToValidate,
mustBeSameLengthAsArgument=mustBeSameLengthAsArgument,
pythonType=types.TupleType,
canBeNone=canBeNone)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(TupleTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
itemsToValidate = min(len(value), self.MaxItemsToValidate)
if itemsToValidate != len(value):
from GeoEco.Logging import Logger
Logger.Debug(_(u'The %(var)s contains %(count1)i items, but
to minimize execution time, only the first %(count2)i items will be
validated. If an invalid item is present, unexpected results may occur.') %
{u'var': variableName, u'count1': len(value), u'count2':
self.MaxItemsToValidate})
for i in range(itemsToValidate):
(elementValueChanged, newElementValue) =
self.ElementType.ValidateValue(value[i], _(u'element %i of the %s (where 0 is
the first element)') % (i, variableName), methodLocals, argMetadata)
if elementValueChanged:
if isinstance(value, types.TupleType):
value = list(value)
value[i] = newElementValue
valueChanged = True
if isinstance(value, types.ListType):
value = tuple(value)
valueChanged = True
return (valueChanged, value)
def ParseValueFromArcGISInputParameterString(self, paramString,
paramDisplayName, paramIndex):
resultList = super(TupleTypeMetadata,
self).ParseValueFromArcGISInputParameterString(paramString, paramDisplayName,
paramIndex)
return tuple(resultList)
class DictionaryTypeMetadata(TypeMetadata):
def __init__(self,
keyType,
valueType,
minLength=0,
maxLength=2147483647,
pythonType=types.DictType,
canBeNone=False):
assert isinstance(keyType, TypeMetadata), u'keyType must be an
instance of TypeMetadata'
assert isinstance(valueType, TypeMetadata), u'valueType must be an
instance of TypeMetadata'
assert isinstance(minLength, types.IntType) and minLength >= 0 and
minLength <= 2147483647, u'minLength must be an integer between 0 and
2147483647, inclusive'
assert isinstance(maxLength, types.IntType) and maxLength >= 0 and
maxLength <= 2147483647, u'maxLength must be an integer between 0 and
2147483647, inclusive'
assert maxLength >= minLength, u'maxLength must be greater than or
equal to minLength'
# Initialize the base class.
super(DictionaryTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone)
self._KeyType = keyType
self._ValueType = valueType
self._MinLength = minLength
self._MaxLength = maxLength
def _GetKeyType(self):
return self._KeyType
KeyType = property(_GetKeyType, doc=DynamicDocString())
def _GetValueType(self):
return self._ValueType
ValueType = property(_GetValueType, doc=DynamicDocString())
def _GetMinLength(self):
return self._MinLength
MinLength = property(_GetMinLength, doc=DynamicDocString())
def _GetMaxLength(self):
return self._MaxLength
MaxLength = property(_GetMaxLength, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(DictionaryTypeMetadata, self).AppendXMLNodes(node, document)
keyTypeNode =
node.appendChild(document.createElement(u'KeyTypeMetadata'))
self.KeyType.AppendXMLNodes(keyTypeNode, document)
valueTypeNode =
node.appendChild(document.createElement(u'ValueTypeMetadata'))
self.ValueType.AppendXMLNodes(valueTypeNode, document)
Metadata.AppendPropertyXMLNode(self, u'MinLength', node, document)
Metadata.AppendPropertyXMLNode(self, u'MaxLength', node, document)
def AppendXMLNodesForValue(self, value, node, document):
raise AssertionError(u'Default values are not currently supported for
parameters of type DictionaryTypeMetadata. Please remove the default value
%s.' % unicode(repr(value)))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(DictionaryTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if len(value) < self.MinLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too short. It must contain at least %(len)i items.') % {u'variable' :
variableName, u'len' : self.MinLength}))
if len(value) > self.MaxLength:
_RaiseException(ValueError(_(u'The length of the %(variable)s
is too long. It must contain no more than %(len)i items.') % {u'variable' :
variableName, u'len' : self.MaxLength}))
for key, val in value.items():
(keyChanged, newKey) = self.ValueType.ValidateValue(val,
_(u'key %s of the %s') % (unicode(repr(key)), variableName), methodLocals,
argMetadata)
(valChanged, newVal) = self.ValueType.ValidateValue(val,
_(u'value of key %s of the %s') % (unicode(repr(key)), variableName),
methodLocals, argMetadata)
if keyChanged and valChanged:
del value[key]
value[newKey] = newVal
elif keyChanged and not valChanged:
del value[key]
value[newKey] = val
elif not keyChanged and valChanged:
value[key] = newVal
valueChanged = keyChanged or valChanged
return (valueChanged, value)
# Types that represents stored objects (files, directories, DB tables, etc.)
class StoredObjectTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self,
typeDisplayName,
isPath=True,
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPStringTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(typeDisplayName, types.UnicodeType),
u'typeDisplayName must be a Unicode string'
assert isinstance(isPath, types.BooleanType), u'isPath must be a
boolean'
assert isinstance(canBeRelativePath, types.BooleanType),
u'canBeRelativePath must be a boolean'
assert not (canBeRelativePath and not isPath), u'If canBeRelativePath
is True, isPath must also be True'
assert isinstance(basePathArgument, (types.UnicodeType,
types.NoneType)), u'basePathArgument must be a Unicode string, or None'
assert not (basePathArgument is not None and not canBeRelativePath),
u'If basePathArgument is not None, canBeRelativePath must also be True'
assert isinstance(useArcGISWorkspace, types.BooleanType),
u'useArcGISWorkspace must be a boolean'
assert not (useArcGISWorkspace and not canBeRelativePath), u'If
useArcGISWorkspace is True, canBeRelativePath must also be True'
assert isinstance(normalizePath, types.BooleanType), u'normalizePath
must be a boolean'
assert isinstance(mustExist, types.BooleanType), u'mustExist must be
a boolean'
assert isinstance(mustNotExist, types.BooleanType), u'mustNotExist
must be a boolean'
assert not mustExist or not mustNotExist, u'mustExist and
mustNotExist cannot both be True'
assert isinstance(deleteIfParameterIsTrue, (types.UnicodeType,
types.NoneType)), u'deleteIfParameterIsTrue must be a Unicode string, or None'
assert not mustNotExist or deleteIfParameterIsTrue is None,
u'deleteIfParameterIsTrue must be None if mustNotExist is True'
assert isinstance(createParentDirectories, types.BooleanType),
u'createParentDirectories must be a boolean'
super(StoredObjectTypeMetadata, self).__init__(minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._TypeDisplayName = typeDisplayName
self._IsPath = isPath
self._CanBeRelativePath = canBeRelativePath
self._BasePathArgument = basePathArgument
self._UseArcGISWorkspace = useArcGISWorkspace
self._NormalizePath = normalizePath
self._MustBeDifferentThanArguments = mustBeDifferentThanArguments
self._MustExist = mustExist
self._MustNotExist = mustNotExist
self._DeleteIfParameterIsTrue = deleteIfParameterIsTrue
self._CreateParentDirectories = createParentDirectories
def _GetTypeDisplayName(self):
return self._TypeDisplayName
TypeDisplayName = property(_GetTypeDisplayName, doc=DynamicDocString())
def _GetIsPath(self):
return self._IsPath
IsPath = property(_GetIsPath, doc=DynamicDocString())
def _GetCanBeRelativePath(self):
return self._CanBeRelativePath
CanBeRelativePath = property(_GetCanBeRelativePath,
doc=DynamicDocString())
def _GetBasePathArgument(self):
return self._BasePathArgument
def _SetBasePathArgument(self, value):
assert isinstance(value, (types.UnicodeType, types.NoneType)),
u'BasePathArgument must be a Unicode string, or None'
self._BasePathArgument = value
BasePathArgument = property(_GetBasePathArgument, _SetBasePathArgument,
doc=DynamicDocString())
def _GetUseArcGISWorkspace(self):
return self._UseArcGISWorkspace
UseArcGISWorkspace = property(_GetUseArcGISWorkspace,
doc=DynamicDocString())
def _GetNormalizePath(self):
return self._NormalizePath
NormalizePath = property(_GetNormalizePath, doc=DynamicDocString())
def _GetMustBeDifferentThanArguments(self):
return self._MustBeDifferentThanArguments
def _SetMustBeDifferentThanArguments(self, value):
assert isinstance(value, (types.ListType, types.TupleType,
types.NoneType)), u'MustBeDifferentThanArguments must be a list or tuple of
Unicode strings, or None'
if value is not None:
if isinstance(value, types.TupleType):
value = list(value)
for v in value:
assert isinstance(value, types.UnicodeType),
u'MustBeDifferentThanArguments must be a list or tuple of Unicode strings, or
None'
self._MustBeDifferentThanArguments = value
MustBeDifferentThanArguments = property(_GetMustBeDifferentThanArguments,
_SetMustBeDifferentThanArguments, doc=DynamicDocString())
def _GetMustExist(self):
return self._MustExist
def _SetMustExist(self, value):
assert isinstance(value, types.BooleanType), u'MustExist must be a
boolean'
self._MustExist = value
MustExist = property(_GetMustExist, _SetMustExist, doc=DynamicDocString())
def _GetMustNotExist(self):
return self._MustNotExist
def _SetMustNotExist(self, value):
assert isinstance(value, types.BooleanType), u'MustNotExist must be a
boolean'
self._MustNotExist = value
MustNotExist = property(_GetMustNotExist, _SetMustNotExist,
doc=DynamicDocString())
def _GetDeleteIfParameterIsTrue(self):
return self._DeleteIfParameterIsTrue
def _SetDeleteIfParameterIsTrue(self, value):
assert isinstance(value, (types.UnicodeType, types.NoneType)),
u'DeleteIfParameterIsTrue must be a Unicode string, or None'
self._DeleteIfParameterIsTrue = value
DeleteIfParameterIsTrue = property(_GetDeleteIfParameterIsTrue,
_SetDeleteIfParameterIsTrue, doc=DynamicDocString())
def _GetCreateParentDirectories(self):
return self._CreateParentDirectories
def _SetCreateParentDirectories(self, value):
assert isinstance(value, types.BooleanType),
u'CreateParentDirectories must be a boolean'
self._CreateParentDirectories = value
CreateParentDirectories = property(_GetCreateParentDirectories,
_SetCreateParentDirectories, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(StoredObjectTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'TypeDisplayName', node,
document)
Metadata.AppendPropertyXMLNode(self, u'IsPath', node, document)
Metadata.AppendPropertyXMLNode(self, u'CanBeRelativePath', node,
document)
Metadata.AppendPropertyXMLNode(self, u'BasePathArgument', node,
document)
Metadata.AppendPropertyXMLNode(self, u'UseArcGISWorkspace', node,
document)
Metadata.AppendPropertyXMLNode(self, u'NormalizePath', node, document)
mustBeDifferentThanArgumentsNode =
node.appendChild(document.createElement(u'MustBeDifferentThanArguments'))
if self.MustBeDifferentThanArguments is not None:
listNode =
mustBeDifferentThanArgumentsNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.MustBeDifferentThanArguments)):
self.AppendXMLNodesForValue(self.MustBeDifferentThanArguments[i], listNode,
document)
Metadata.AppendPropertyXMLNode(self, u'MustExist', node, document)
Metadata.AppendPropertyXMLNode(self, u'MustNotExist', node, document)
Metadata.AppendPropertyXMLNode(self, u'DeleteIfParameterIsTrue',
node, document)
Metadata.AppendPropertyXMLNode(self, u'CreateParentDirectories',
node, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(StoredObjectTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
exists = None
isCorrectType = None
if self.IsPath:
valueChanged, value, exists, isCorrectType =
self._CanonicalizePath(value, argMetadata, methodLocals)
if self.MustBeDifferentThanArguments is not None and methodLocals
is not None:
for arg in self.MustBeDifferentThanArguments:
assert methodLocals.has_key(arg), _(u'To validate the
%(param1)s of the method being validated, that method must also have an
parameter named %(param2)s.') % {u'param1' : variableName, u'param2' : arg}
if value == methodLocals[arg]:
same = True
elif hasattr(os.path,'samefile'):
try:
same = os.path.samefile(value, methodLocals[arg])
except OSError:
same = False
else:
same = os.path.normcase(os.path.abspath(value)) ==
os.path.normcase(os.path.abspath(methodLocals[arg]))
if same:
_RaiseException(ValueError(_(u'The %(param1)s and the
%(param2)s parameter refer to the same %(type)s (%(value)s). You must not
specify the same %(type)s.') % {u'param1' : variableName, u'param2' : arg,
u'type' : self.TypeDisplayName, u'value' : value}))
from GeoEco.Logging import Logger
oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
Logger.SetLogInfoAsDebug(True)
try:
if self.MustExist or self.MustNotExist or
self.DeleteIfParameterIsTrue is not None:
assert self.DeleteIfParameterIsTrue is None or
methodLocals.has_key(self.DeleteIfParameterIsTrue), _(u'To validate the
%(param1)s of the method being validated, that method must also have an
parameter named %(param2)s.') % {u'param1' : variableName, u'param2' :
self.DeleteIfParameterIsTrue}
if exists is None:
exists, isCorrectType = self.Exists(value,
argMetadata, methodLocals)
if exists:
if isCorrectType:
if self.MustNotExist or
self.DeleteIfParameterIsTrue is not None and not
methodLocals[self.DeleteIfParameterIsTrue]:
_RaiseException(ValueError(_(u'The %(type)s
%(value)s, specified for the %(variable)s, already exists. Please delete it
and try again, or specify a non-existing %(type)s.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName}))
if self.DeleteIfParameterIsTrue is not None and
methodLocals[self.DeleteIfParameterIsTrue]:
self.Delete(value, argMetadata, methodLocals)
else:
if self.MustNotExist:
_RaiseException(ValueError(_(u'The value
specified for the %(variable)s, %(value)s, already exists although it is not
a %(type)s. Please delete it and try again, or specify a non-existing
object.') % {u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName}))
if self.MustExist or self.DeleteIfParameterIsTrue
is not None:
_RaiseException(ValueError(_(u'The value
specified for the %(variable)s, %(value)s, exists but it is not a %(type)s.
Please specify a %(type)s.') % {u'type' : self.TypeDisplayName, u'value' :
value, u'variable' : variableName}))
elif self.MustExist:
_RaiseException(ValueError(_(u'The %(type)s
%(value)s, specified for the %(variable)s, does not exist. Please specify an
existing %(type)s.') % {u'type' : self.TypeDisplayName, u'value' : value,
u'variable' : variableName}))
if self.CreateParentDirectories and
(re.match(u'^[A-Za-z]:[\\\\/]', value) or re.match(u'^[\\\\/]', value)) and
not (os.path.dirname(value).lower().endswith(u'.mdb') and
os.path.isfile(os.path.dirname(value))):
from GeoEco.DataManagement.Directories import Directory
Directory.Create(os.path.dirname(value))
finally:
Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
return (valueChanged, value)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
valueChanged = False
if self.IsRelativePath(value):
if not self.CanBeRelativePath:
_RaiseException(ValueError(_(u'The %(variable)s specifies the
relative path "%(value)s" but relative paths are not allowed. Please provide
an absolute path and try again.') % {u'variable' : variableName, u'value' :
value}))
madeAbsolute = False
if self.BasePathArgument is not None:
if not methodLocals.has_key(self.BasePathArgument):
_RaiseException(RuntimeError(_(u'Programming error in
this tool. The metadata for the %(variable)s specifies that when the caller
provides a relative path, the base path can be obtained from the %(base)s
parameter, but that parameter does not exist. Please contact the author of
this tool for assistance.') % {u'variable' : variableName, u'base':
self.BasePathArgument}))
if methodLocals[self.BasePathArgument] is not None:
value2 =
os.path.join(methodLocals[self.BasePathArgument], value)
if value != value2:
value = value2
valueChanged = True
madeAbsolute = True
if not madeAbsolute and self.UseArcGISWorkspace:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp is not None and isinstance(gp.Workspace, basestring)
and len(gp.Workspace) > 0:
value2 = os.path.join(gp.Workspace, value)
if value != value2:
value = value2
valueChanged = True
madeAbsolute = True
if not madeAbsolute:
value2 = os.path.abspath(value)
if value != value2:
value = value2
valueChanged = True
if self.NormalizePath:
value2 = os.path.normpath(value)
if value != value2:
value = value2
valueChanged = True
return valueChanged, value, None, None # valueChanged, value,
exists, isCorrectType
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Exists method.' % className))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Delete method.' % className))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
if isinstance(cls, StoredObjectTypeMetadata):
className = cls.__class__.__name__
else:
className = cls.__name__
_RaiseException(NotImplementedError(u'Programming error in the %s
class: the class does not implement the Copy method.' % className))
@classmethod
def IsRelativePath(cls, p):
if p is None:
return False
if sys.platform == u'win32':
if re.match(u'^[A-Za-z]:[\\\\/]', p) or
re.match(u'^[\\\\/][\\\\/]\w', p):
return False
else:
if p.startswith(u'/'):
return False
return True
class FileTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
mayBeCompressed=False,
decompressedFileToUse=u'*',
typeDisplayName=_(u'file'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(mayBeCompressed, types.BooleanType),
u'mayBeCompressed must be a boolean'
super(FileTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
self._MayBeCompressed = mayBeCompressed
self._DecompressedFileToUse = decompressedFileToUse
def _GetMayBeCompressed(self):
return self._MayBeCompressed
MayBeCompressed = property(_GetMayBeCompressed, doc=DynamicDocString())
def _GetDecompressedFileToUse(self):
return self._DecompressedFileToUse
DecompressedFileToUse = property(_GetDecompressedFileToUse,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(FileTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'MayBeCompressed', node,
document)
Metadata.AppendPropertyXMLNode(self, u'DecompressedFileToUse', node,
document)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Files import File
return File.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Files import File
File.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Files import File
File.Copy(source, dest, overwriteExisting=overwriteExisting)
class TextFileTypeMetadata(FileTypeMetadata):
def __init__(self,
mayBeCompressed=False,
decompressedFileToUse=u'*',
typeDisplayName=_(u'text file'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DETextFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(TextFileTypeMetadata,
self).__init__(mayBeCompressed=mayBeCompressed,
decompressedFileToUse=decompressedFileToUse,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
class DirectoryTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'directory'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEFolderTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(DirectoryTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
return Directory.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
Directory.Delete(name, removeTree=True)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Directories import Directory
Directory.Copy(source, dest,
deleteExistingDestinationDirectory=overwriteExisting,
overwriteExistingFiles=overwriteExisting)
# ArcGIS types
class ArcGISGeoDatasetTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'geographic dataset'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.DEGeoDatasetTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISGeoDatasetTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISGeoDatasetTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
# See if it exists.
from GeoEco.Logging import Logger
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp is None:
Logger.RaiseException(RuntimeError(_(u'The ArcGIS geoprocessor
must be initialized before this function may be called. Please call
GeoprocessorManager.InitializeGeoprocessor or
GeoprocessorManager.SetGeoprocessor before calling this function.')))
exists = gp.Exists(name)
isCorrectType = False
# If it exists, see if the describe object has an Extent
# property. If it does, then it is a "geodataset".
if exists:
d = gp.Describe(name)
isCorrectType = d is not None and hasattr(d, 'Extent') and
isinstance(d.Extent, basestring) and len(d.Extent) > 0
# Log a debug message indicating what happened.
if not exists:
Logger.Debug(_(u'The geographic dataset %(path)s does not
exist.') % {u'path': name})
else:
if isCorrectType:
Logger.Debug(_(u'The geographic dataset %(path)s exists.') %
{u'path': name})
else:
Logger.Debug(_(u'%(path)s exists but it is a %(actual)s, not
a geographic dataset.') % {u'path': name, u'actual': d.DataType})
# Return the results.
return (exists, isCorrectType)
class ArcGISRasterTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedPixelTypes=None,
typeDisplayName=_(u'raster'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.DataSourcesRaster.DERasterDatasetTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.DataSourcesRaster',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedPixelTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedPixelTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedPixelTypes, types.TupleType):
allowedPixelTypes = list(allowedPixelTypes)
if allowedPixelTypes is not None:
for s in allowedPixelTypes:
assert isinstance(s, types.UnicodeType), u'allowedPixelTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedPixelTypes = map(unicode.strip, map(unicode.lower,
allowedPixelTypes))
else:
self._AllowedPixelTypes = None
super(ArcGISRasterTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedPixelTypes(self):
return self._AllowedPixelTypes
AllowedPixelTypes = property(_GetAllowedPixelTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISRasterTypeMetadata, self).AppendXMLNodes(node, document)
allowedPixelTypesNode =
node.appendChild(document.createElement(u'AllowedPixelTypes'))
if self.AllowedPixelTypes is not None:
listNode =
allowedPixelTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedPixelTypes)):
self.AppendXMLNodesForValue(self.AllowedPixelTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISRasterTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedPixelTypes is not None:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp.Exists(value) and gp.Describe(value).PixelType.lower() not
in self.AllowedPixelTypes:
if len(self.AllowedPixelTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, is a %(pt)s %(type)s but this function
requires a %(allowed)s %(type)s. Please provide a %(allowed)s %(type)s.') %
{u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName, u'pt': self.GetPixelTypeName(gp.Describe(value).PixelType),
u'allowed': self.GetPixelTypeName(self.AllowedPixelTypes[0])}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, is a %(pt)s %(type)s but this function
requires a %(type)s with one of the following pixel types: %(allowed)s.
Please provide a %(type)s with an allowed pixel type.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName, u'pt':
self.GetPixelTypeName(gp.Describe(value).PixelType), u'allowed': unicode('\',
\''.join(map(self.GetPixelTypeName, self.AllowedPixelTypes)))}))
return (valueChanged, value)
def GetPixelTypeName(self, pixelType):
name = _(u'unknown data type')
if isinstance(pixelType, basestring) and len(pixelType) >= 2:
if pixelType[0] == u'u' or pixelType[0] == u'U':
name = _('%s-bit unsigned integer') % pixelType[1:]
elif pixelType[0] == u's' or pixelType[0] == u'S':
name = _('%s-bit signed integer') % pixelType[1:]
elif pixelType[0] == u'f' or pixelType[0] == u'F':
name = _('%s-bit floating point') % pixelType[1:]
return name
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
return ArcGISRaster.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
ArcGISRaster.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
ArcGISRaster.Copy(source, dest, overwriteExisting=overwriteExisting)
class ArcGISRasterLayerTypeMetadata(ArcGISRasterTypeMetadata):
def __init__(self,
allowedPixelTypes=None,
typeDisplayName=_(u'raster or raster layer'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPRasterLayerTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISRasterLayerTypeMetadata,
self).__init__(allowedPixelTypes=allowedPixelTypes,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISRasterLayerTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name,
[u'rasterdataset', u'rasterlayer', u'rasterband'], _(u'ArcGIS raster, raster
layer, or raster band'))
class ArcGISFeatureClassTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedShapeTypes=None,
typeDisplayName=_(u'feature class'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DEFeatureClassTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedShapeTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedShapeTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedShapeTypes, types.TupleType):
allowedShapeTypes = list(allowedShapeTypes)
if allowedShapeTypes is not None:
for s in allowedShapeTypes:
assert isinstance(s, types.UnicodeType), u'allowedShapeTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedShapeTypes = map(unicode.strip, map(unicode.lower,
allowedShapeTypes))
else:
self._AllowedShapeTypes = None
super(ArcGISFeatureClassTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedShapeTypes(self):
return self._AllowedShapeTypes
AllowedShapeTypes = property(_GetAllowedShapeTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISFeatureClassTypeMetadata, self).AppendXMLNodes(node,
document)
allowedShapeTypesNode =
node.appendChild(document.createElement(u'AllowedShapeTypes'))
if self.AllowedShapeTypes is not None:
listNode =
allowedShapeTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedShapeTypes)):
self.AppendXMLNodesForValue(self.AllowedShapeTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISFeatureClassTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedShapeTypes is not None:
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp.Exists(value) and gp.Describe(value).ShapeType.lower() not
in self.AllowedShapeTypes:
if len(self.AllowedShapeTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the shape type \'%(shape)s\', but this
function requires a %(type)s with the shape type \'%(allowed)s\'. Please
provide a %(type)s with shape type \'%(allowed)s\'.') % {u'type' :
self.TypeDisplayName, u'value' : value, u'variable' : variableName, u'shape':
gp.Describe(value).ShapeType.lower(), u'allowed': self.AllowedShapeTypes[0]}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the shape type \'%(shape)s\', but this
function requires a %(type)s with one of the following shape types:
\'%(allowed)s\'. Please provide a %(type)s with an allowed shape type.') %
{u'type' : self.TypeDisplayName, u'value' : value, u'variable' :
variableName, u'shape': gp.Describe(value).ShapeType.lower(), u'allowed':
unicode('\', \''.join(map(str, self.AllowedShapeTypes)))}))
return (valueChanged, value)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'featureclass',
u'shapefile'], _(u'ArcGIS feature class'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'featureclass',
u'shapefile'], _(u'ArcGIS feature class'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'featureclass', u'shapefile'], _(u'ArcGIS feature class'))
class ArcGISFeatureLayerTypeMetadata(ArcGISFeatureClassTypeMetadata):
def __init__(self,
allowedShapeTypes=None,
typeDisplayName=_(u'feature class or layer'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPFeatureLayerTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISFeatureLayerTypeMetadata,
self).__init__(allowedShapeTypes=allowedShapeTypes,
typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISFeatureLayerTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'featureclass',
u'shapefile', u'featurelayer'], _(u'ArcGIS feature class or layer'))
class ShapefileTypeMetadata(FileTypeMetadata):
def __init__(self,
typeDisplayName=_(u'shapefile'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=u'.+\.[Ss][Hh][Pp]$',
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Catalog.DEShapeFileTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Catalog',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ShapefileTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
return Shapefile.Exists(name)
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
Shapefile.Delete(name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.DataManagement.Shapefiles import Shapefile
Shapefile.Copy(source, dest, overwriteExisting=overwriteExisting)
class ArcGISWorkspaceTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'workspace'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DEWorkspaceTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISWorkspaceTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'workspace',
u'folder'], _(u'ArcGIS workspace'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'workspace',
u'folder'], _(u'ArcGIS workspace'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'workspace', u'folder'], _(u'ArcGIS workspace'))
class ArcGISTableTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
typeDisplayName=_(u'table'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
createParentDirectories=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.DETableTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
super(ArcGISTableTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=True,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=createParentDirectories,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.DeleteArcGISObject(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
GeoprocessorManager.CopyArcGISObject(source, dest, overwriteExisting,
[u'table', u'dbasetable', u'textfile', u'shapefile', u'featureclass',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table'))
class ArcGISTableViewTypeMetadata(ArcGISTableTypeMetadata):
def __init__(self,
typeDisplayName=_(u'table or table view'),
canBeRelativePath=True,
basePathArgument=None,
useArcGISWorkspace=True,
normalizePath=True,
mustBeDifferentThanArguments=None,
mustExist=False,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPTableViewTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing'):
super(ArcGISTableViewTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
canBeRelativePath=canBeRelativePath,
basePathArgument=basePathArgument,
useArcGISWorkspace=useArcGISWorkspace,
normalizePath=normalizePath,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly)
def _CanonicalizePath(self, value, argMetadata, methodLocals):
# It could be a layer or it could be a path to something.
# Layers will already exist and do not require
# canonicalization. If the value already exists, assume it is
# a layer and return successfully. (Note that it might not be
# the correct type, but this will be handled by
# StoredObjectTypeMetadata.ValidateValue).
exists, isCorrectType = self.Exists(value, argMetadata, methodLocals)
if exists:
return False, value, exists, isCorrectType
# It did not exist. Canonicalize it.
valueChanged, value, exists, isCorrectType =
super(ArcGISTableViewTypeMetadata, self)._CanonicalizePath(value,
argMetadata, methodLocals)
# If the canonicalized form is different than the original, we
# have to check its existence again later, if necessary.
# Return None for the existence parameters.
if valueChanged:
return True, value, None, None
# The canonicalized form is no different than the orginal.
# Therefore it will not be necessary to check its existence
# again later. Return the results of our check.
return False, value, False, False
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
from GeoEco.ArcGIS import GeoprocessorManager
return GeoprocessorManager.ArcGISObjectExists(name, [u'table',
u'dbasetable', u'textfile', u'featureclass', u'shapefile',
u'relationshipclass', u'rastercatalog', u'coveragefeatureclass',
u'tableview', u'featurelayer', u'layer'], _(u'ArcGIS table or table view'))
class ArcGISFieldTypeMetadata(StoredObjectTypeMetadata):
def __init__(self,
allowedFieldTypes=None,
typeDisplayName=_(u'field'),
mustBeDifferentThanArguments=None,
mustExist=False,
mustNotExist=False,
deleteIfParameterIsTrue=None,
minLength=1,
maxLength=255,
mustMatchRegEx=None,
canBeNone=False,
arcGISType=u'ESRI.ArcGIS.Geodatabase.FieldTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geodatabase',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True):
assert isinstance(allowedFieldTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedFieldTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedFieldTypes, types.TupleType):
allowedFieldTypes = list(allowedFieldTypes)
if allowedFieldTypes is not None:
for s in allowedFieldTypes:
assert isinstance(s, types.UnicodeType), u'allowedFieldTypes
must be a list or tuple of Unicode strings, or None.'
self._AllowedFieldTypes = map(unicode.strip, map(unicode.lower,
allowedFieldTypes))
else:
self._AllowedFieldTypes = None
super(ArcGISFieldTypeMetadata,
self).__init__(typeDisplayName=typeDisplayName,
isPath=False,
canBeRelativePath=False,
basePathArgument=None,
useArcGISWorkspace=False,
normalizePath=False,
mustBeDifferentThanArguments=mustBeDifferentThanArguments,
mustExist=mustExist,
mustNotExist=mustNotExist,
deleteIfParameterIsTrue=deleteIfParameterIsTrue,
createParentDirectories=False,
minLength=minLength,
maxLength=maxLength,
mustMatchRegEx=mustMatchRegEx,
canBeNone=canBeNone,
arcGISType=arcGISType,
arcGISAssembly=arcGISAssembly,
canBeArcGISInputParameter=canBeArcGISInputParameter,
canBeArcGISOutputParameter=canBeArcGISOutputParameter)
def _GetAllowedFieldTypes(self):
return self._AllowedFieldTypes
AllowedFieldTypes = property(_GetAllowedFieldTypes,
doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(ArcGISFieldTypeMetadata, self).AppendXMLNodes(node, document)
allowedFieldTypesNode =
node.appendChild(document.createElement(u'AllowedFieldTypes'))
if self.AllowedFieldTypes is not None:
listNode =
allowedFieldTypesNode.appendChild(document.createElement(u'ArrayList'))
for i in range(len(self.AllowedFieldTypes)):
self.AppendXMLNodesForValue(self.AllowedFieldTypes[i],
listNode, document)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(ArcGISFieldTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None and self.AllowedFieldTypes is not None and
methodLocals is not None and argMetadata.ArcGISParameterDependencies is not
None and len(argMetadata.ArcGISParameterDependencies) > 0 and
methodLocals[argMetadata.ArcGISParameterDependencies[0]] is not None:
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
fieldDataType =
conn.GetFieldDataType(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value)
if fieldDataType is not None and fieldDataType.lower() not in
self.AllowedFieldTypes:
if len(self.AllowedFieldTypes) == 1:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the data type \'%(dt)s\', but this
function requires a %(type)s with the data type \'%(allowed)s\'. Please
provide a %(type)s with data type \'%(allowed)s\'.') % {u'type' :
self.TypeDisplayName, u'value' :
os.path.join(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value), u'variable' : variableName, u'dt': fieldDataType, u'allowed':
self.AllowedFieldTypes[0]}))
else:
_RaiseException(ValueError(_(u'The %(type)s %(value)s,
specified for the %(variable)s, has the data type \'%(dt)s\', but this
function requires a %(type)s with one of the following data types:
\'%(allowed)s\'. Please provide a %(type)s with an allowed data type.') %
{u'type' : self.TypeDisplayName, u'value' :
os.path.join(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
value), u'variable' : variableName, u'dt': fieldDataType, u'allowed':
unicode('\', \''.join(map(str, self.AllowedFieldTypes)))}))
return (valueChanged, value)
@classmethod
def Exists(cls, name, argMetadata=None, methodLocals=None):
assert methodLocals is not None and argMetadata is not None and
argMetadata.ArcGISParameterDependencies is not None and
len(argMetadata.ArcGISParameterDependencies) == 1,
u'ArcGISFieldTypeMetadata.Exists requires that methodLocals and argMetadata
be provided, and that argMetadata.ArcGISParameterDependencies[0] be set to
the parameter that specifies the field\'s table.'
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
exists =
conn.FieldExists(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
name)
return exists, exists
@classmethod
def Delete(cls, name, argMetadata=None, methodLocals=None):
assert methodLocals is not None and argMetadata is not None and
argMetadata.ArcGISParameterDependencies is not None and
len(argMetadata.ArcGISParameterDependencies) == 1,
u'ArcGISFieldTypeMetadata.Delete requires that methodLocals and argMetadata
be provided, and that argMetadata.ArcGISParameterDependencies[0] be set to
the parameter that specifies the field\'s table.'
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
conn.DeleteField(methodLocals[argMetadata.ArcGISParameterDependencies[0]],
name)
@classmethod
def Copy(cls, source, dest, overwriteExisting=False, argMetadata=None,
methodLocals=None):
_RaiseException(NotImplementedError(u'ArcGISFieldTypeMetadata.Copy is
not implemented.'))
class CoordinateSystemTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(CoordinateSystemTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPCoordinateSystemTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class EnvelopeTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(EnvelopeTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=u'([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)',
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPEnvelopeTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
@classmethod
def ParseCoordinatesFromString(cls, value):
if value is None:
return None, None, None, None
assert isinstance(value, basestring), u'value must be a string, or
None'
coords = value.split()
return float(coords[0]), float(coords[1]), float(coords[2]),
float(coords[3]) # left, bottom, right, top
class LinearUnitTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(LinearUnitTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPLinearUnitTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class MapAlgebraExpressionTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(MapAlgebraExpressionTypeMetadata, self).__init__(minLength=1,
maxLength=4000,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.SpatialAnalystUI.GPSAMapAlgebraExpTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.SpatialAnalystUI',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
class PointTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(PointTypeMetadata, self).__init__(minLength=1,
mustMatchRegEx=u'([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)\\s+([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)',
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPPointTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
@classmethod
def ParseCoordinatesFromString(cls, value):
if value is None:
return None, None
assert isinstance(value, basestring), u'value must be a string, or
None'
coords = value.split()
return float(coords[0]), float(coords[1])
class SpatialReferenceTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(SpatialReferenceTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPSpatialReferenceTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
from GeoEco.ArcGIS import _ArcGISObjectWrapper
if isinstance(value, _ArcGISObjectWrapper):
return False, value
(valueChanged, value) = super(SpatialReferenceTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
return (valueChanged, value)
class SQLWhereClauseTypeMetadata(UnicodeStringTypeMetadata):
def __init__(self, canBeNone=False):
super(SQLWhereClauseTypeMetadata, self).__init__(minLength=1,
maxLength=2147483647,
mustMatchRegEx=None,
canBeNone=canBeNone,
arcGISType=u'ESRI.ArcGIS.Geoprocessing.GPSQLExpressionTypeClass',
arcGISAssembly=u'ESRI.ArcGIS.Geoprocessing',
canBeArcGISInputParameter=True,
canBeArcGISOutputParameter=True)
# NumPy and SciPy types
#
# Note: do not move import statements out of the functions to the module
level.
# We cannot require NumPy and SciPy to be installed just to import this
module.
class NumPyArrayTypeMetadata(TypeMetadata):
def __init__(self,
dimensions=None,
minShape=None,
maxShape=None,
allowedDTypes=None,
canBeNone=False):
assert isinstance(dimensions, (types.IntType, types.NoneType)),
u'dimensions must be an integer, or None'
assert dimensions is None or dimensions > 0, u'dimensions, if
provided, must be greater than zero'
assert isinstance(minShape, (types.NoneType, types.ListType,
types.TupleType)), u'minShape must be a list or tuple of integers, or None'
if isinstance(minShape, types.TupleType):
minShape = list(minShape)
assert minShape is None or dimensions is not None and len(minShape)
== dimensions, u'If minShape is provided, dimensions must also be provided,
and len(minShape) must equal dimensions'
if minShape is not None:
for value in minShape:
assert isinstance(value, types.IntType) and value >= 0, u'All
elements of minShape must be non-negative integers.'
assert isinstance(maxShape, (types.NoneType, types.ListType,
types.TupleType)), u'maxShape must be a list or tuple of integers, or None'
if isinstance(maxShape, types.TupleType):
maxShape = list(maxShape)
assert maxShape is None or dimensions is not None and len(maxShape)
== dimensions, u'If maxShape is provided, dimensions must also be provided,
and len(maxShape) must equal dimensions'
if maxShape is not None:
for value in maxShape:
assert isinstance(value, types.IntType) and value >= 0, u'All
elements of maxShape must be non-negative integers.'
assert isinstance(allowedDTypes, (types.NoneType, types.ListType,
types.TupleType)), u'allowedDTypes must be a list or tuple of Unicode
strings, or None.'
if isinstance(allowedDTypes, types.TupleType):
allowedDTypes = list(allowedDTypes)
if allowedDTypes is not None:
for value in allowedDTypes:
assert isinstance(value, types.UnicodeType) and len(value) >=
0, u'All elements of allowedDTypes must be non-empty Unicode strings.'
# We cannot assume that numpy can be imported. We must allow
instances of
# this class to be constructed without failing when numpy is not
# installed. But if numpy is installed, we initialize our pythonType
to
# the appropriate class.
try:
import numpy
pythonType = numpy.ndarray
except:
pythonType = object
super(NumPyArrayTypeMetadata, self).__init__(pythonType=pythonType,
canBeNone=canBeNone)
self._Dimensions = dimensions
self._MinShape = minShape
self._MaxShape = maxShape
self._AllowedDTypes = allowedDTypes
def _GetDimensions(self):
return self._Dimensions
Dimensions = property(_GetDimensions, doc=DynamicDocString())
def _GetMinShape(self):
return self._MinShape
MinShape = property(_GetMinShape, doc=DynamicDocString())
def _GetMaxShape(self):
return self._MaxShape
MaxShape = property(_GetMaxShape, doc=DynamicDocString())
def _GetAllowedDTypes(self):
return self._AllowedDTypes
AllowedDTypes = property(_GetAllowedDTypes, doc=DynamicDocString())
def AppendXMLNodes(self, node, document):
super(NumPyArrayTypeMetadata, self).AppendXMLNodes(node, document)
Metadata.AppendPropertyXMLNode(self, u'Dimensions', node, document)
minShapeNode = node.appendChild(document.createElement(u'MinShape'))
if self.MinShape is not None:
listNode =
minShapeNode.appendChild(document.createElement(u'ArrayList'))
for value in self.MinShape:
listNode.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
maxShapeNode = node.appendChild(document.createElement(u'MaxShape'))
if self.MaxShape is not None:
listNode =
maxShapeNode.appendChild(document.createElement(u'ArrayList'))
for value in self.MaxShape:
listNode.appendChild(document.createElement(u'int')).appendChild(document.createTextNode(unicode(value)))
allowedDTypesNode =
node.appendChild(document.createElement(u'AllowedDTypes'))
if self.AllowedDTypes is not None:
listNode =
allowedDTypesNode.appendChild(document.createElement(u'ArrayList'))
for value in self.AllowedDTypes:
listNode.appendChild(document.createElement(u'string')).appendChild(document.createTextNode(value))
def ValidateValue(self, value, variableName, methodLocals=None,
argMetadata=None):
(valueChanged, value) = super(NumPyArrayTypeMetadata,
self).ValidateValue(value, variableName, methodLocals, argMetadata)
if value is not None:
if self.Dimensions is not None:
if self.Dimensions != value.ndim:
_RaiseException(ValueError(_(u'The NumPy array provided
for the %(variable)s must have %(dim1)i dimensions. The array you provided
has %(dim2)i.') % {u'variable' : variableName, u'dim1' : self.Dimensions,
u'dim2' : value.ndim}))
if self.MinShape is not None:
for i in range(self.Dimensions):
if value.shape[i] < self.MinShape[i]:
_RaiseException(ValueError(_(u'The NumPy array
provided for the %(variable)s must have the minimum dimensions %(dim1)i. The
array you provided has the dimensions %(dim2)i.') % {u'variable' :
variableName, u'dim1' : repr(self.MinShape), u'dim2' :
repr(list(value.shape))}))
if self.MaxShape is not None:
for i in range(self.Dimensions):
if value.shape[i] > self.MaxShape[i]:
_RaiseException(ValueError(_(u'The NumPy array
provided for the %(variable)s must have the maximum dimensions %(dim1)i. The
array you provided has the dimensions %(dim2)i.') % {u'variable' :
variableName, u'dim1' : repr(self.MaxShape), u'dim2' :
repr(list(value.shape))}))
if self.AllowedDTypes is not None and unicode(value.dtype.name)
not in self.AllowedDTypes:
_RaiseException(ValueError(_(u'The NumPy array provided for
the %(variable)s must have one of the following dtypes: %(types)s. The array
you provided has the dtype %(type)s.') % {u'variable' : variableName,
u'types' : repr(self.AllowedDTypes), u'type' : unicode(value.dtype.name)}))
return (valueChanged, value)
###############################################################################
# Names exported by this module
###############################################################################
__all__ = ['AnyObjectTypeMetadata',
'NoneTypeMetadata',
'ClassTypeMetadata',
'ClassInstanceTypeMetadata',
'ClassOrClassInstanceTypeMetadata',
'BooleanTypeMetadata',
'DateTimeTypeMetadata',
'FloatTypeMetadata',
'IntegerTypeMetadata',
'UnicodeStringTypeMetadata',
'SequenceTypeMetadata',
'ListTypeMetadata',
'TupleTypeMetadata',
'DictionaryTypeMetadata',
'StoredObjectTypeMetadata',
'FileTypeMetadata',
'TextFileTypeMetadata',
'DirectoryTypeMetadata',
'ArcGISGeoDatasetTypeMetadata',
'ArcGISRasterTypeMetadata',
'ArcGISRasterLayerTypeMetadata',
'ArcGISFeatureClassTypeMetadata',
'ArcGISFeatureLayerTypeMetadata',
'ShapefileTypeMetadata',
'ArcGISWorkspaceTypeMetadata',
'ArcGISTableTypeMetadata',
'ArcGISTableViewTypeMetadata',
'ArcGISFieldTypeMetadata',
'CoordinateSystemTypeMetadata',
'EnvelopeTypeMetadata',
'LinearUnitTypeMetadata',
'MapAlgebraExpressionTypeMetadata',
'PointTypeMetadata',
'SpatialReferenceTypeMetadata',
'SQLWhereClauseTypeMetadata',
'NumPyArrayTypeMetadata']
Archives powered by MHonArc.