def _processAttribs(attribDict): """ @summary: Processes attribute dictionaries to make sure keys and values are encoded correctly @todo: Add encoding """ newDict = {} for k, v in attribDict.items(): newDict[toUnicode(k)] = toUnicode(v) return newDict
def stringifyError(err): """ @summary: This really only adds information for urllib2.HTTPErrors that include an 'Error-Message' header @param err: The exception to stringify """ try: return err.hdrs['Error-Message'] except: return toUnicode(err)
def __init__(self, tag, attrib={}, value=None, namespace=-1, **extra): """ @summary: Element constructor @param tag: The tag for the element (string or QName) @param attrib: A dictionary of element attributes @param value: The value for this element (goes in element.text) @param namespace: (optional) The namespace of this element @param extra: (optional) Extra named parameters that will be added to the element's attributes @note: Providing None for the namespace will result in a QName without a namespace @note: Providing -1 for the namespace will result in the default namespace (__DEFAULT_NAMESPACE__) being used """ elQName = _getElemQName(namespace, tag) ET.Element.__init__(self, elQName, attrib=_processAttribs(attrib), **extra) if value is not None: self.text = toUnicode(value)
def SubElement(parent, tag, attrib={}, value=None, namespace=-1, **extra): """ @summary: Tells the parent to create a child ElementTree Element, adds a value and a namespace to it, and then returns it @see: ElementTree.SubElement @param parent: The parent Element @param tag: A tag for the element (either string or QName) @param attrib: (optional) A dictionary of element attributes @param value: (optional) The value for this element (goes in element.text) @param namespace: (optional) The namespace of this element @param extra: (optional) Extra named parameters that will be added to the element's attributes @note: Providing None for the namespace will result in a QName without a namespace @note: Providing -1 for the namespace will result in the default namespace (__DEFAULT_NAMESPACE__) being used """ elQName = _getElemQName(namespace, tag) subEl = ET.SubElement(parent, elQName, attrib=_processAttribs(attrib), **extra) if value is not None: subEl.text = toUnicode(value) return subEl
if body is None and len(parameters) > 0 and method.lower() == "post": body = urlparams else: url = "%s?%s" % (url, urlparams) req = urllib2.Request(url, data=body, headers=headers) req.add_header('User-Agent', self.UA_STRING) req.get_method = lambda: method.upper() try: ret = urllib2.urlopen(req) except urllib2.HTTPError, e: #print e.headers['Error-Message'] raise e except Exception, e: raise Exception('Error returning from request to %s (%s)' % (url, toUnicode(e))) else: resp = ''.join(ret.readlines()) if objectify: return self.objectify(resp) else: return resp # ......................................... def objectify(self, xmlString): """ @summary: Takes an XML string and processes it into a python object @param xmlString: The xml string to turn into an object @note: Uses LmAttList and LmAttObj @note: Object attributes are defined on the fly """
class _Client(object): """ @summary: Private Lifemapper client class """ __version__ = "3.2.0" # ......................................... def __init__(self, server=WEBSITE_ROOT): """ @summary: Constructor of LMClient @param server: (optional) The Lifemapper web server root address """ self.server = server # ......................................... def checkVersion(self, clientName="lmClientLib", verStr=None): """ @summary: Checks the version of the client library against the versions reported by the web server @param clientName: (optional) Check this client if not the client library @param verStr: (optional) The version string of the client to check @raise OutOfDateException: Raised if the client is out of date and cannot continue """ res = self.makeRequest(LM_CLIENT_VERSION_URL, objectify=True) for client in res: if client.name == clientName: minVersionStr = client.versions.minimum curVersionStr = client.versions.current minVersion = self.getVersionNumbers(verStr=minVersionStr) curVersion = self.getVersionNumbers(verStr=curVersionStr) myVersion = self.getVersionNumbers(verStr=verStr) if myVersion < minVersion: raise OutOfDateException(myVersion, minVersion) if myVersion < curVersion: warnings.warn("Client is not latest version: (%s < %s)" % \ (myVersion, curVersion), Warning) # ......................................... def getVersionNumbers(self, verStr=None): """ @summary: Splits a version string into a tuple @param verStr: The version number as a string, if None, get the client version @return: Tuple of version (major, minor, revision, status) """ if verStr is None: verStr = self.__version__ major = 0 minor = 0 revision = 0 status = "zzzz" vStr = verStr.strip().split(' ') if len(vStr) > 1: status = vStr[1] mmrList = vStr[0].split('.') # Split on '.' try: # If not all parts are specified, specifies as many as possible major = int(mmrList[0]) minor = int(mmrList[1]) revision = int(mmrList[2]) except: pass return (major, minor, revision, status) # ......................................... def autoUnzipShapefile(self, cnt, filePath, overwrite=False): """ @summary: Attempt to unzip a zipped shapefile. @param cnt: The zipped shapefile content @param filePath: If a directory is specified, unzip the shapefile there. If a .zip path is specified, write out the zipfile as-is. If a .shp path is specified, write out the shapefile files with that name as the base. @param overwrite: (optional) Boolean indicating if the files should be overwritten if present @note: If specifying a directory as the filePath, it should exist """ if os.path.isdir(filePath): with zipfile.ZipFile(StringIO.StringIO(cnt), 'r', allowZip64=True) as zf: # Check to see if files exist nameList = zf.namelist() if not overwrite: for name in nameList: if os.path.exists(os.path.join(filePath, name)): raise Exception( "File %s, already exists and overwrite is: %s" % (os.path.join(filePath, name), overwrite)) zf.extractall(filePath) else: base, ext = os.path.splitext(filePath) if ext == '.zip': with open(filePath, 'wb') as outF: outF.write(cnt) elif ext == '.shp': # Check to see if filePath exists # Able to write if path doesn't exist or overwrite is true if not os.path.exists(filePath) or overwrite: with zipfile.ZipFile(StringIO.StringIO(cnt), 'r', allowZip64=True) as zf: for name in zf.namelist(): fCnt = zf.read(name) fBase, fExt = os.path.splitext(name) with open( os.path.join(filePath, '%s%s' % (base, fExt)), 'wb') as outF: outF.write(fCnt) else: raise Exception, "%s already exists and overwrite is: %s" % ( filePath, overwrite) else: raise Exception, "Do not know how to handle file path: %s" % filePath # ......................................... def getAutozipShapefileStream(self, fn): """ @summary: Automatically creates a zipped version of a shapefile from the shapefile's .shp file. Finds the rest of the files it needs and includes them in one package @param fn: Path to the shapefile's .shp file @return: The zipped shapefile @rtype: String """ files = [] if fn.endswith('.shp'): for f in glob.iglob("%s*" % fn.strip('shp')): ext = os.path.splitext(f)[1] if ext in SHAPEFILE_EXTENSIONS: files.append(f) else: raise Exception("Filename must end in '.shp'") outStream = StringIO.StringIO() zf = zipfile.ZipFile(outStream, 'w', allowZip64=True) for f in files: zf.write(f, os.path.basename(f)) zf.close() outStream.seek(0) return outStream.getvalue() # ......................................... def getCount(self, url, parameters=[]): """ @summary: Gets the item count from a count service @param url: A URL pointing to a count service end-point @param parameters: (optional) List of query parameters for the request """ obj = self.makeRequest(url, method="GET", parameters=parameters, objectify=True) count = int(obj.items.itemCount) return count # ......................................... def getList(self, url, parameters=[]): """ @summary: Gets a list of items from a list service @param url: A URL pointing to a list service end-point @param parameters: (optional) List of query parameters for the request """ obj = self.makeRequest(url, method="GET", parameters=parameters, objectify=True) try: if isinstance(obj.items, ListType): lst = obj.items else: lst = obj.items.item if lst is not None: if not isinstance(lst, ListType): lst = [lst] return lst except Exception: #print e pass return [] # ......................................... def makeRequest(self, url, method="GET", parameters=[], body=None, headers={}, objectify=False): """ @summary: Performs an HTTP request @param url: The url endpoint to make the request to @param method: (optional) The HTTP method to use for the request @param parameters: (optional) List of url parameters @param body: (optional) The payload of the request @param headers: (optional) Dictionary of HTTP headers @param objectify: (optional) Should the response be turned into an object @return: Response from the server """ parameters = removeNonesFromTupleList(parameters) urlparams = urllib.urlencode(parameters) if body is None and len(parameters) > 0 and method.lower() == "post": body = urlparams else: url = "%s?%s" % (url, urlparams) req = urllib2.Request(url, data=body, headers=headers) req.add_header( 'User-Agent', 'LMClient/%s (Lifemapper Python Client Library; http://lifemapper.org; [email protected])' % self.__version__) try: ret = urllib2.urlopen(req) except urllib2.HTTPError, e: #print e.headers['Error-Message'] raise e except Exception, e: raise Exception('Error returning from request to %s (%s)' % (url, toUnicode(e)))
if body is None and len(parameters) > 0 and method.lower() == "post": body = urlparams else: url = "%s?%s" % (url, urlparams) req = urllib2.Request(url, data=body, headers=headers) #req.add_header('User-Agent', self.UA_STRING) req.get_method = lambda: method.upper() try: #ret = urllib2.urlopen(req) ret = opener(req) except urllib2.HTTPError, e: #print e.headers['Error-Message'] raise e except Exception, e: raise Exception( 'Error returning from request to %s (%s)' % (url, toUnicode(e))) else: resp = ''.join(ret.readlines()) return resp # ............................................................................. def getOpeners(env, userId, pwd): """ @summary: Get public and authenticated url openers for requests @param userId: The user id to log in with @param pwd: The user's password @return: Public and authenticated openers """ publicOpener = MyOpener(env).getOpener() if userId is not None and pwd is not None: authOpener = MyOpener(env, userId=userId, pwd=pwd).getOpener()