class Process(object): """ :param handler: A callable that gets invoked for each incoming request. It should accept a single :class:`pywps.app.WPSRequest` argument and return a :class:`pywps.app.WPSResponse` object. :param string identifier: Name of this process. :param string title: Human readable title of process. :param string abstract: Brief narrative description of the process. :param list keywords: Keywords that characterize a process. :param inputs: List of inputs accepted by this process. They should be :class:`~LiteralInput` and :class:`~ComplexInput` and :class:`~BoundingBoxInput` objects. :param outputs: List of outputs returned by this process. They should be :class:`~LiteralOutput` and :class:`~ComplexOutput` and :class:`~BoundingBoxOutput` objects. :param metadata: List of metadata advertised by this process. They should be :class:`pywps.app.Common.Metadata` objects. """ def __init__(self, handler, identifier, title, abstract='', keywords=[], profile=[], metadata=[], inputs=[], outputs=[], version='None', store_supported=False, status_supported=False, grass_location=None): self.identifier = identifier self.handler = handler self.title = title self.abstract = abstract self.keywords = keywords self.metadata = metadata self.profile = profile self.version = version self.inputs = inputs self.outputs = outputs self.uuid = None self.status_location = '' self.status_url = '' self.workdir = None self._grass_mapset = None self.grass_location = grass_location self.service = None if store_supported: self.store_supported = 'true' else: self.store_supported = 'false' if status_supported: self.status_supported = 'true' else: self.status_supported = 'false' @property def json(self): return { 'version': self.version, 'identifier': self.identifier, 'title': self.title, 'abstract': self.abstract, 'keywords': self.keywords, 'metadata': [m for m in self.metadata], 'inputs': [i.json for i in self.inputs], 'outputs': [o.json for o in self.outputs], 'store_supported': self.store_supported, 'status_supported': self.status_supported, 'profile': [p for p in self.profile], } def execute(self, wps_request, uuid): self._set_uuid(uuid) self. async = False response_cls = get_response("execute") wps_response = response_cls(wps_request, process=self, uuid=self.uuid) LOGGER.debug( 'Check if status storage and updating are supported by this process' ) if wps_request.store_execute == 'true': if self.store_supported != 'true': raise StorageNotSupported( 'Process does not support the storing of the execute response' ) if wps_request.status == 'true': if self.status_supported != 'true': raise OperationNotSupported( 'Process does not support the updating of status') wps_response.store_status_file = True self. async = True else: wps_response.store_status_file = False LOGGER.debug( 'Check if updating of status is not required then no need to spawn a process' ) wps_response = self._execute_process(self. async, wps_request, wps_response) return wps_response def _set_uuid(self, uuid): """Set uuid and status location path and url """ self.uuid = uuid for inpt in self.inputs: inpt.uuid = uuid for outpt in self.outputs: outpt.uuid = uuid file_path = config.get_config_value('server', 'statuspath') file_url = config.get_config_value('server', 'statusurl') self.status_location = os.path.join(file_path, str(self.uuid)) + '.xml' self.status_url = os.path.join(file_url, str(self.uuid)) + '.xml' def _execute_process(self, async, wps_request, wps_response): """Uses :module:`pywps.processing` module for sending process to background BUT first, check for maxprocesses configuration value :param async: run in asynchronous mode :return: wps_response or None """ maxparallel = int( config.get_config_value('server', 'parallelprocesses')) running = dblog.get_running().count() stored = dblog.get_stored().count() # async if async: # run immedietly if running < maxparallel or maxparallel == -1: wps_response._update_status(WPS_STATUS.ACCEPTED, u"PyWPS Request accepted", 0) self._run_async(wps_request, wps_response) # try to store for later usage else: maxprocesses = int( config.get_config_value('server', 'maxprocesses')) if stored >= maxprocesses: raise ServerBusy( 'Maximum number of parallel running processes reached. Please try later.' ) LOGGER.debug("Store process in job queue, uuid=%s", self.uuid) dblog.store_process(self.uuid, wps_request) wps_response._update_status( WPS_STATUS.ACCEPTED, u'PyWPS Process stored in job queue', 0) # not async else: if running >= maxparallel and maxparallel != -1: raise ServerBusy( 'Maximum number of parallel running processes reached. Please try later.' ) wps_response._update_status(WPS_STATUS.ACCEPTED, u"PyWPS Request accepted", 0) wps_response = self._run_process(wps_request, wps_response) return wps_response
class Process(object): """ :param handler: A callable that gets invoked for each incoming request. It should accept a single :class:`~WPSRequest` argument and return a :class:`~WPSResponse` object. :param identifier: Name of this process. :param inputs: List of inputs accepted by this process. They should be :class:`~LiteralInput` and :class:`~ComplexInput` and :class:`~BoundingBoxInput` objects. :param outputs: List of outputs returned by this process. They should be :class:`~LiteralOutput` and :class:`~ComplexOutput` and :class:`~BoundingBoxOutput` objects. """ def __init__(self, handler, identifier, title, abstract='', profile=[], metadata=[], inputs=[], outputs=[], version='None', store_supported=False, status_supported=False): self.identifier = identifier self.handler = handler self.title = title self.abstract = abstract self.metadata = metadata self.profile = profile self.version = version self.inputs = inputs self.outputs = outputs self.uuid = None self.status_location = '' self.status_url = '' self.workdir = None if store_supported: self.store_supported = 'true' else: self.store_supported = 'false' if status_supported: self.status_supported = 'true' else: self.status_supported = 'false' def capabilities_xml(self): doc = WPS.Process(OWS.Identifier(self.identifier), OWS.Title(self.title)) if self.abstract: doc.append(OWS.Abstract(self.abstract)) # TODO: See Table 32 Metadata in OGC 06-121r3 #for m in self.metadata: # doc.append(OWS.Metadata(m)) if self.profile: doc.append(OWS.Profile(self.profile)) if self.version != 'None': doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = self.version else: doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = 'undefined' return doc def describe_xml(self): input_elements = [i.describe_xml() for i in self.inputs] output_elements = [i.describe_xml() for i in self.outputs] doc = E.ProcessDescription(OWS.Identifier(self.identifier), OWS.Title(self.title)) doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = self.version if self.store_supported == 'true': doc.attrib['storeSupported'] = self.store_supported if self.status_supported == 'true': doc.attrib['statusSupported'] = self.status_supported if self.abstract: doc.append(OWS.Abstract(self.abstract)) for m in self.metadata: doc.append(OWS.Metadata({'{http://www.w3.org/1999/xlink}title': m})) for p in self.profile: doc.append(WPS.Profile(p)) if input_elements: doc.append(E.DataInputs(*input_elements)) doc.append(E.ProcessOutputs(*output_elements)) return doc def execute(self, wps_request, uuid): self._set_uuid(uuid) async = False wps_response = WPSResponse(self, wps_request, self.uuid) LOGGER.debug( 'Check if status storage and updating are supported by this process' ) if wps_request.store_execute == 'true': if self.store_supported != 'true': raise StorageNotSupported( 'Process does not support the storing of the execute response' ) if wps_request.status == 'true': if self.status_supported != 'true': raise OperationNotSupported( 'Process does not support the updating of status') wps_response.status = WPSResponse.STORE_AND_UPDATE_STATUS async = True else: wps_response.status = WPSResponse.STORE_STATUS LOGGER.debug( 'Check if updating of status is not required then no need to spawn a process' ) wps_response = self._execute_process(async, wps_request, wps_response) return wps_response def _set_uuid(self, uuid): """Set uuid and status ocation apth and url """ self.uuid = uuid file_path = config.get_config_value('server', 'outputpath') file_url = config.get_config_value('server', 'outputurl') self.status_location = os.path.join(file_path, str(self.uuid)) + '.xml' self.status_url = os.path.join(file_url, str(self.uuid)) + '.xml' def _execute_process(self, async, wps_request, wps_response): """Uses :module:`multiprocessing` module for sending process to background BUT first, check for maxprocesses configuration value :param async: run in asynchronous mode :return: wps_response or None """ maxparalel = int(config.get_config_value('server', 'parallelprocesses')) running = len(dblog.get_running()) stored = len(dblog.get_stored()) # async if async: # run immedietly if running < maxparalel: self._run_async(wps_request, wps_response) # try to store for later usage else: wps_response = self._store_process(stored, wps_request, wps_response) # not async else: if running < maxparalel: wps_response = self._run_process(wps_request, wps_response) else: raise ServerBusy( 'Maximum number of paralel running processes reached. Please try later.' ) return wps_response
class Process(object): """ :param handler: A callable that gets invoked for each incoming request. It should accept a single :class:`pywps.app.WPSRequest` argument and return a :class:`pywps.app.WPSResponse` object. :param string identifier: Name of this process. :param string title: Human readable title of process. :param string abstract: Brief narrative description of the process. :param list keywords: Keywords that characterize a process. :param inputs: List of inputs accepted by this process. They should be :class:`~LiteralInput` and :class:`~ComplexInput` and :class:`~BoundingBoxInput` objects. :param outputs: List of outputs returned by this process. They should be :class:`~LiteralOutput` and :class:`~ComplexOutput` and :class:`~BoundingBoxOutput` objects. :param metadata: List of metadata advertised by this process. They should be :class:`pywps.app.Common.Metadata` objects. """ def __init__(self, handler, identifier, title, abstract='', keywords=[], profile=[], metadata=[], inputs=[], outputs=[], version='None', store_supported=False, status_supported=False, grass_location=None): self.identifier = identifier self.handler = handler self.title = title self.abstract = abstract self.keywords = keywords self.metadata = metadata self.profile = profile self.version = version self.inputs = inputs self.outputs = outputs self.uuid = None self.status_location = '' self.status_url = '' self.workdir = None self._grass_mapset = None self.grass_location = grass_location self.service = None if store_supported: self.store_supported = 'true' else: self.store_supported = 'false' if status_supported: self.status_supported = 'true' else: self.status_supported = 'false' def capabilities_xml(self): doc = WPS.Process(OWS.Identifier(self.identifier), OWS.Title(self.title)) if self.abstract: doc.append(OWS.Abstract(self.abstract)) if self.keywords: kws = map(OWS.Keyword, self.keywords) doc.append(OWS.Keywords(*kws)) for m in self.metadata: doc.append(OWS.Metadata(dict(m))) if self.profile: doc.append(OWS.Profile(self.profile)) if self.version != 'None': doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = self.version else: doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = 'undefined' return doc def describe_xml(self): input_elements = [i.describe_xml() for i in self.inputs] output_elements = [i.describe_xml() for i in self.outputs] doc = E.ProcessDescription(OWS.Identifier(self.identifier), OWS.Title(self.title)) doc.attrib[ '{http://www.opengis.net/wps/1.0.0}processVersion'] = self.version if self.store_supported == 'true': doc.attrib['storeSupported'] = self.store_supported if self.status_supported == 'true': doc.attrib['statusSupported'] = self.status_supported if self.abstract: doc.append(OWS.Abstract(self.abstract)) if self.keywords: kws = map(OWS.Keyword, self.keywords) doc.append(OWS.Keywords(*kws)) for m in self.metadata: doc.append(OWS.Metadata(dict(m))) for p in self.profile: doc.append(WPS.Profile(p)) if input_elements: doc.append(E.DataInputs(*input_elements)) doc.append(E.ProcessOutputs(*output_elements)) return doc def execute(self, wps_request, uuid): self._set_uuid(uuid) self. async = False response_cls = get_response("execute") wps_response = response_cls(wps_request, process=self, uuid=self.uuid) LOGGER.debug( 'Check if status storage and updating are supported by this process' ) if wps_request.store_execute == 'true': if self.store_supported != 'true': raise StorageNotSupported( 'Process does not support the storing of the execute response' ) if wps_request.status == 'true': if self.status_supported != 'true': raise OperationNotSupported( 'Process does not support the updating of status') wps_response.status = STATUS.STORE_AND_UPDATE_STATUS self. async = True else: wps_response.status = STATUS.STORE_STATUS LOGGER.debug( 'Check if updating of status is not required then no need to spawn a process' ) wps_response = self._execute_process(self. async, wps_request, wps_response) return wps_response def _set_uuid(self, uuid): """Set uuid and status location path and url """ self.uuid = uuid for inpt in self.inputs: inpt.uuid = uuid for outpt in self.outputs: outpt.uuid = uuid file_path = config.get_config_value('server', 'outputpath') file_url = config.get_config_value('server', 'outputurl') self.status_location = os.path.join(file_path, str(self.uuid)) + '.xml' self.status_url = os.path.join(file_url, str(self.uuid)) + '.xml' def _execute_process(self, async, wps_request, wps_response): """Uses :module:`pywps.processing` module for sending process to background BUT first, check for maxprocesses configuration value :param async: run in asynchronous mode :return: wps_response or None """ maxparallel = int( config.get_config_value('server', 'parallelprocesses')) running = dblog.get_running().count() stored = dblog.get_stored().count() # async if async: # run immedietly if running < maxparallel or maxparallel == -1: self._run_async(wps_request, wps_response) # try to store for later usage else: wps_response = self._store_process(stored, wps_request, wps_response) # not async else: if running < maxparallel or maxparallel == -1: wps_response = self._run_process(wps_request, wps_response) else: raise ServerBusy( 'Maximum number of parallel running processes reached. Please try later.' ) return wps_response