def test_wps_request3(): # Supply process input arguments polygon = [(-102.8184, 39.5273), (-102.8184, 37.418), (-101.2363, 37.418), (-101.2363, 39.5273), (-102.8184, 39.5273)] featureCollection = GMLMultiPolygonFeatureCollection([polygon]) processid = 'gov.usgs.cida.gdp.wps.algorithm.FeatureWeightedGridStatisticsAlgorithm' inputs = [("FEATURE_ATTRIBUTE_NAME", "the_geom"), ("DATASET_URI", "dods://igsarm-cida-thredds1.er.usgs.gov:8080/thredds/dodsC/dcp/conus_grid.w_meta.ncml"), ("DATASET_ID", "ccsm3_a1b_tmax"), ("TIME_START", "1960-01-01T00:00:00.000Z"), ("TIME_END", "1960-12-31T00:00:00.000Z"), ("REQUIRE_FULL_COVERAGE", "true"), ("DELIMITER", "COMMA"), ("STATISTICS", "MEAN"), ("STATISTICS", "MINIMUM"), ("STATISTICS", "MAXIMUM"), ("STATISTICS", "WEIGHT_SUM"), ("STATISTICS", "VARIANCE"), ("STATISTICS", "STD_DEV"), ("STATISTICS", "COUNT"), ("GROUP_BY", "STATISTIC"), ("SUMMARIZE_TIMESTEP", "false"), ("SUMMARIZE_FEATURE_ATTRIBUTE", "false"), ("FEATURE_COLLECTION", featureCollection)] output = "OUTPUT" # build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs, output=output) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_USGSExecuteRequest3.xml'), 'rb').read() assert compare_xml(request, _request) is True
def compare_io(self, name, fn, fmt): """Start the dummy process, post the request and check the response matches the input data.""" # Note that `WPSRequest` calls `get_inputs_from_xml` which converts base64 input to bytes # See `_get_rawvalue_value` client = client_for(Service(processes=[create_fmt_process(name, fn, fmt)])) data = get_data(fn, fmt.encoding) wps = WPSExecution() doc = wps.buildRequest('test-fmt', inputs=[('complex', ComplexDataInput(data, mimeType=fmt.mime_type, encoding=fmt.encoding))], mode='sync') resp = client.post_xml(doc=doc) assert_response_success(resp) wps.parseResponse(resp.xml) out = wps.processOutputs[0].data[0] if 'gml' in fmt.mime_type: xml_orig = etree.tostring(etree.fromstring(data.encode('utf-8'))).decode('utf-8') xml_out = etree.tostring(etree.fromstring(out.decode('utf-8'))).decode('utf-8') # Not equal because the output includes additional namespaces compared to the origin. # self.assertEqual(xml_out, xml_orig) else: self.assertEqual(out.strip(), data.strip())
def check_status(url=None, response=None, sleep_secs=2, verify=False): """ Run owslib.wps check_status with additional exception handling. :param verify: Flag to enable SSL verification. Default: False :return: OWSLib.wps.WPSExecution object. """ execution = WPSExecution() if response: LOGGER.debug("using response document ...") xml = response elif url: LOGGER.debug('using status_location url ...') xml = requests.get(url, verify=verify).content else: raise Exception( "you need to provide a status-location url or response object.") # TODO: see owslib: https://github.com/geopython/OWSLib/pull/477 execution.checkStatus(response=xml, sleepSecs=sleep_secs) if execution.response is None: raise Exception("check_status failed!") # TODO: workaround for owslib type change of reponse if not isinstance(execution.response, etree._Element): execution.response = etree.fromstring(execution.response) return execution
def check_status(url=None, response=None, sleep_secs=2, verify=False): """ Run owslib.wps check_status with additional exception handling. :param verify: Flag to enable SSL verification. Default: False :return: OWSLib.wps.WPSExecution object. """ execution = WPSExecution() if response: logger.debug("using response document ...") xml = response elif url: logger.debug('using status_location url ...') xml = requests.get(url, verify=verify).content else: raise Exception("you need to provide a status-location url or response object.") if type(xml) is unicode: xml = xml.encode('utf8', errors='ignore') execution.checkStatus(response=xml, sleepSecs=sleep_secs) if execution.response is None: raise Exception("check_status failed!") # TODO: workaround for owslib type change of reponse if not isinstance(execution.response, etree._Element): execution.response = etree.fromstring(execution.response) return execution
def test_wps_request3(): # Supply process input argument wfsUrl = "http://igsarm-cida-gdp2.er.usgs.gov:8082/geoserver/wfs" query = WFSQuery("sample:CONUS_States", propertyNames=['the_geom', "STATE"], filters=["CONUS_States.508", "CONUS_States.469"]) featureCollection = WFSFeatureCollection(wfsUrl, query) processid = 'gov.usgs.cida.gdp.wps.algorithm.FeatureWeightedGridStatisticsAlgorithm' inputs = [ ("FEATURE_ATTRIBUTE_NAME", "STATE"), ("DATASET_URI", "dods://igsarm-cida-thredds1.er.usgs.gov:8080/thredds/dodsC/dcp/conus_grid.w_meta.ncml" ), ("DATASET_ID", "ccsm3_a1b_tmax"), ("DATASET_ID", "ccsm3_a1b_pr"), ("DATASET_ID", "ccsm3_a1fi_tmax"), ("TIME_START", "1960-01-01T00:00:00.000Z"), ("TIME_END", "1960-12-31T00:00:00.000Z"), ("REQUIRE_FULL_COVERAGE", "true"), ("DELIMITER", "COMMA"), ("STATISTICS", "MEAN"), ("STATISTICS", "MINIMUM"), ("STATISTICS", "MAXIMUM"), ("STATISTICS", "WEIGHT_SUM"), ("STATISTICS", "VARIANCE"), ("STATISTICS", "STD_DEV"), ("STATISTICS", "COUNT"), ("GROUP_BY", "STATISTIC"), ("SUMMARIZE_TIMESTEP", "true"), ("SUMMARIZE_FEATURE_ATTRIBUTE", "true"), ("FEATURE_COLLECTION", featureCollection) ] output = "OUTPUT" # build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs, output=output) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_USGSExecuteRequest2.xml'), 'rb').read() assert compare_xml(request, _request) is True
def checkStatus(cls, instance): if not instance.is_initialized(): exception = Exception("Not initialized!") log.exception("Not initialized!") raise exception if instance.execution and isinstance( instance.execution, WebProcessingServiceExecution) and instance.execution.response: _e = WPSExecution(version=instance.version, url=instance.url, username=instance.username, password=instance.password, verbose=False) _e.request = instance.execution.request _e.statusLocation = instance.execution.status_location _e.serviceInstance = instance.service_instance try: _e.checkStatus(sleepSecs=3) except: log.exception( "Exception while Checking WPS Execution Status {}".format( _e)) if _e.status: cls._update_instance_execution_status(instance, _e) else: raise Exception("Status check failed") return instance.execution.status else: exception = Exception("No running executions!") log.exception("No running executions!") raise exception
def test_wps_response_with_lineage(): execution = WPSExecution() xml = open(resource_file('wps_HummingbirdExecuteResponse1.xml'), 'rb').read() execution.checkStatus(response=xml) assert execution.isSucceded() assert execution.creationTime == '2018-05-08T14:00:54Z' # check lineage input with literal data inp = execution.dataInputs[0] assert inp.identifier == 'test' assert inp.title == 'Select the test you want to run.' assert inp.abstract == 'CF-1.6=Climate and Forecast Conventions (CF)' assert inp.data[0] == 'CF-1.6' # check lineage input with reference inp = execution.dataInputs[1] assert inp.identifier == 'dataset' assert inp.title == 'Upload your NetCDF file here' assert inp.abstract == 'or enter a URL pointing to a NetCDF file.' assert inp.reference.startswith('https://www.esrl.noaa.gov/') # check output with reference outp = execution.processOutputs[0] assert outp.identifier == 'output' assert outp.title == 'Test Report' assert outp.abstract == 'Compliance checker test report.' assert outp.reference.startswith('http://localhost:8090/wpsoutputs')
def execute_job(self, process_id, wps_inputs, wps_outputs, mode, job_uuid): """ Real execution of the process by active Celery Worker. """ execution = WPSExecution(version="2.0", url="localhost") xml_request = execution.buildRequest(process_id, wps_inputs, wps_outputs, mode=mode, lineage=True) wps_request = WPSRequest() wps_request.identifier = process_id wps_request.set_version("2.0.0") request_parser = wps_request._post_request_parser( wps_request.WPS.Execute().tag) # noqa: W0212 request_parser(xml_request) # NOTE: # Setting 'status = false' will disable async execution of 'pywps.app.Process.Process' # but this is needed since this job is running within Celery worker already async # (daemon process can't have children processes) # Because if how the code in PyWPS is made, we have to re-enable creation of status file wps_request.status = "false" wps_response = super(WorkerService, self).execute(process_id, wps_request, job_uuid) wps_response.store_status_file = True # update execution status with actual status file and apply required references execution = check_wps_status( location=wps_response.process.status_location, settings=self.settings) execution.request = xml_request return execution
def check_wps_status( location=None, # type: Optional[str] response=None, # type: Optional[XML] sleep_secs=2, # type: int verify=True, # type: bool settings=None, # type: Optional[AnySettingsContainer] ): # type: (...) -> WPSExecution """ Run :func:`owslib.wps.WPSExecution.checkStatus` with additional exception handling. :param location: job URL or file path where to look for job status. :param response: WPS response document of job status. :param sleep_secs: number of seconds to sleep before returning control to the caller. :param verify: Flag to enable SSL verification. :param settings: Application settings to retrieve any additional request parameters as applicable. :return: OWSLib.wps.WPSExecution object. """ def _retry_file(): LOGGER.warning( "Failed retrieving WPS status-location, attempting with local file." ) out_path = get_wps_local_status_location(location, settings) if not out_path: raise HTTPNotFound( "Could not find file resource from [{}].".format(location)) LOGGER.info("Resolved WPS status-location using local file reference.") return open(out_path, "r").read() execution = WPSExecution() if response: LOGGER.debug("Retrieving WPS status from XML response document...") xml = response elif location: xml_resp = HTTPNotFound() try: LOGGER.debug("Attempt to retrieve WPS status-location from URL...") xml_resp = request_extra("get", location, verify=verify, settings=settings) xml = xml_resp.content except Exception as ex: LOGGER.debug("Got exception during get status: [%r]", ex) xml = _retry_file() if xml_resp.status_code == HTTPNotFound.code: LOGGER.debug("Got not-found during get status: [%r]", xml) xml = _retry_file() else: raise Exception( "Missing status-location URL/file reference or response with XML object." ) if isinstance(xml, str): xml = xml.encode("utf8", errors="ignore") execution.checkStatus(response=xml, sleepSecs=sleep_secs) if execution.response is None: raise Exception("Missing response, cannot check status.") if not isinstance(execution.response, lxml.etree._Element): # noqa execution.response = lxml.etree.fromstring(execution.response) return execution
def execute_job( self, job, # type: Job wps_inputs, # type: List[WPS_InputData] wps_outputs, # type: List[WPS_OutputRequested] remote_process, # type: Optional[Process] headers, # type: Optional[AnyHeadersContainer] ): # type: (...) -> WPSExecution """ Real execution of the process by active Celery Worker. """ process_id = job.process execution = WPSExecution(version="2.0", url="localhost") xml_request = execution.buildRequest(process_id, wps_inputs, wps_outputs, mode=job.execution_mode, lineage=True) wps_request = WorkerRequest(http_headers=headers) wps_request.identifier = process_id wps_request.check_and_set_language(job.accept_language) wps_request.set_version("2.0.0") request_parser = wps_request._post_request_parser( wps_request.WPS.Execute().tag) # noqa: W0212 request_parser( xml_request ) # parses the submitted inputs/outputs data and request parameters # NOTE: # Setting 'status = false' will disable async execution of 'pywps.app.Process.Process' # but this is needed since this job is running within Celery worker already async # (daemon process can't have children processes). wps_request.status = "false" # When 'execute' is called, pywps will in turn call 'prepare_process_for_execution', # which then setups and retrieves currently loaded 'local' processes. # Since only local processes were defined by 'get_pywps_service', # a temporary process must be added for remote providers execution. if not remote_process: worker_process_id = process_id else: worker_process_id = f"wps_package-{process_id}-{job.uuid}" self.dispatched_processes[worker_process_id] = remote_process wps_response = super(WorkerService, self).execute(worker_process_id, wps_request, job.uuid) # re-enable creation of status file so we can find it since we disabled 'status' earlier for sync execution wps_response.store_status_file = True # update execution status with actual status file and apply required references execution = check_wps_status( location=wps_response.process.status_location, settings=self.settings) execution.request = xml_request return execution
def getOWSLibExecutionResponse(cls, instance): _e = None if instance.execution.response: _e = WPSExecution() try: _e.checkStatus(url=instance.url, response=str(instance.execution.response), sleepSecs=0) except: pass return _e
def test_wps_request11_bbox(): processid = "bbox" bbox = BoundingBoxDataInput([51.9, 7.0, 53.0, 8.0]) inputs = [("bbox", bbox)] # Build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_EmuExecuteRequest11.xml'), 'rb').read() assert compare_xml(request, _request) is True
def test_wps_request9(): # Process input/output arguments processid = "helloworld" inputs = [("user", 'Pingu')] # Build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_EmuExecuteRequest9.xml'), 'rb').read() assert compare_xml(request, _request) is True
def test_wps_request5(): # Process input/output arguments processid = "reprojectCoords" inputs = [("coords", "http://rsg.pml.ac.uk/wps/testdata/coords.txt"), ("outputSRS", "EPSG:32630"), ("inputSRS", "EPSG:4326")] # build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_PMLExecuteRequest5.xml'), 'rb').read() assert compare_xml(request, _request) is True
def test_wps_request8(): # Process input/ouutput arguments processid = "wordcount" textdoc = ComplexDataInput("Alice was beginning to get very tired ...") inputs = [("text", textdoc), ] outputs = [("output", True), ] # Build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs, output=outputs, async=True, lineage=True) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_EmuExecuteRequest8.xml'), 'rb').read() assert compare_xml(request, _request) is True
def test_wps_request4(): # Process input/ouutput arguments processid = "reprojectImage" inputs = [("inputImage", "http://rsg.pml.ac.uk/wps/testdata/elev_srtm_30m.img"), ("outputSRS", "EPSG:4326")] output = "outputImage" # build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs, output=output) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_PMLExecuteRequest4.xml'), 'rb').read() assert compare_xml(request, _request) is True
def test_wps_ncml(): client = client_for(Service(processes=[NcMLAgg()], cfgfiles=CFG_FILE)) resp = client.get(service='wps', request='execute', version='1.0.0', identifier='ncml') assert_response_success(resp) ex = WPSExecution() ex.parseResponse(resp.xml) d1, d2, d3 = ex.processOutputs ncml = d3.retrieveData() assert ncml.strip().startswith("<")
def test_wps_request7(): # Process input/ouutput arguments processid = "wordcount" textdoc = ComplexDataInput("http://emu.readthedocs.org/en/latest/index.html") inputs = [("text", textdoc), ] outputs = [("output", True)] # Build XML request for WPS process execution, sync request execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs, output=outputs, mode=SYNC, lineage=False) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_EmuExecuteRequest7.xml'), 'rb').read() print(request) assert compare_xml(request, _request) is True
def execute_process(client, identifier, inputs, output_names=("output_netcdf", )) -> xr.Dataset: """Execute a process using the test client, and return the 'output_netcdf' output as an xarray.Dataset""" request_doc = WPS.Execute(OWS.Identifier(identifier), WPS.DataInputs(*inputs), version="1.0.0") response = client.post_xml(doc=request_doc) assert_response_success(response) execution = WPSExecution() execution.parseResponse(response.xml) outputs = get_file_outputs(execution, output_names=output_names) return outputs
def test_wps_request6(): # Process input/output arguments processid = "v.net.path" inputs = [ ("input", "http://rsg.pml.ac.uk/wps/example/graph.gml"), ("file", "1 -960123.1421801624 4665723.56559387 -101288.65106088226 5108200.011823481" ) ] # Build XML request for WPS process execution execution = WPSExecution() requestElement = execution.buildRequest(processid, inputs) request = etree.tostring(requestElement) # Compare to cached XML request _request = open(resource_file('wps_PMLExecuteRequest6.xml'), 'rb').read() assert compare_xml(request, _request) is True
def execute(identifier, inputs=[], wps_host=None, wps_client=None, version='1.0.0'): if wps_host: wps = WebProcessingService(wps_host, version) return wps.execute(identifier, inputs=inputs) else: y = '' for data_input in inputs: y += '{0}={1};'.format(data_input[0], data_input[1]) y = y[:-1] response = wps_client.get( ('?service=WPS&request=execute&version={0}&' 'identifier={1}&DataInputs={2}').format(version, identifier, y)) wps_reader = WPSReader() element = wps_reader.readFromString(response.get_data()) execution = WPSExecution() execution._parseExecuteResponse(element) return execution
def execute_process(client, identifier, inputs, output_names=("output", )) -> xr.Dataset: """Execute a process using the test client, and return the 'output_netcdf' output as an xarray.Dataset""" request_doc = WPS.Execute(OWS.Identifier(identifier), WPS.DataInputs(*inputs), version="1.0.0") response = client.post_xml(doc=request_doc) try: assert_response_success(response) except AssertionError as e: exception = response.xpath("//ows:Exception")[0] exception_code = exception.get("exceptionCode") message = exception[0].text output_message = f"{exception_code}: {message}" raise ProcessError(output_message) from e execution = WPSExecution() execution.parseResponse(response.xml) outputs = get_outputs(execution, output_names=output_names) return outputs
def execute(identifier, inputs=[], wps_host=None, wps_client=None, version='1.0.0'): """WPS execute response. Parameters ---------- identifer : string inputs : list of tuples wps_host : string wps_client : pywps.tests.WpsClient version : string Returns ------- out : list of ? """ if wps_host: wps = WebProcessingService(wps_host, version) return wps.execute(identifier, inputs=inputs) else: y = '' for data_input in inputs: y += '{0}={1};'.format(data_input[0], data_input[1]) y = y[:-1] response = wps_client.get( ('?service=WPS&request=execute&version={0}&' 'identifier={1}&DataInputs={2}').format(version, identifier, y)) wps_reader = WPSReader() element = wps_reader.readFromString(response.get_data()) execution = WPSExecution() execution._parseExecuteResponse(element) return execution
def wps_execute(self, version, accept): wps_url = get_wps_url(self.settings) if version == "1.0.0": test_content = "Test file in Docker - WPS KVP" wps_method = "GET" elif version == "2.0.0": test_content = "Test file in Docker - WPS XML" wps_method = "POST" else: raise ValueError("Invalid WPS version: {}".format(version)) test_content += " {} request - Accept {}".format(wps_method, accept.split("/")[-1].upper()) with contextlib.ExitStack() as stack_exec: # setup dir_name = tempfile.gettempdir() tmp_path = tempfile.NamedTemporaryFile(dir=dir_name, mode="w", suffix=".txt") tmp_file = stack_exec.enter_context(tmp_path) # noqa tmp_file.write(test_content) tmp_file.seek(0) for mock_exec in mocked_execute_process(): stack_exec.enter_context(mock_exec) # execute if version == "1.0.0": wps_inputs = ["file={}@mimeType={}".format(tmp_file.name, CONTENT_TYPE_TEXT_PLAIN)] wps_params = { "service": "WPS", "request": "Execute", "version": version, "identifier": self.process_id, "DataInputs": wps_inputs, } wps_headers = {"Accept": accept} wps_data = None else: wps_inputs = [("file", ComplexDataInput(tmp_file.name, mimeType=CONTENT_TYPE_TEXT_PLAIN))] wps_outputs = [(self.out_key, True)] # as reference wps_exec = WPSExecution(version=version, url=wps_url) wps_req = wps_exec.buildRequest(self.process_id, wps_inputs, wps_outputs) wps_data = lxml.etree.tostring(wps_req) wps_headers = {"Accept": accept, "Content-Type": CONTENT_TYPE_APP_XML} wps_params = None resp = mocked_sub_requests(self.app, wps_method, wps_url, params=wps_params, data=wps_data, headers=wps_headers, only_local=True) assert resp.status_code in [200, 201], \ "Failed with: [{}]\nTest: [{}]\nReason:\n{}".format(resp.status_code, test_content, resp.text) # parse response status if accept == CONTENT_TYPE_APP_XML: assert resp.content_type in CONTENT_TYPE_ANY_XML, test_content xml = lxml.etree.fromstring(str2bytes(resp.text)) status_url = xml.get("statusLocation") job_id = status_url.split("/")[-1] elif accept == CONTENT_TYPE_APP_JSON: assert resp.content_type == CONTENT_TYPE_APP_JSON, test_content status_url = resp.json["location"] job_id = resp.json["jobID"] assert status_url assert job_id # job monitoring result = self.monitor_job(status_url) self.validate_outputs(job_id, result, test_content)
def check_wps_status( location=None, # type: Optional[str] response=None, # type: Optional[xml_util.XML] sleep_secs=2, # type: int verify=True, # type: bool settings=None, # type: Optional[AnySettingsContainer] ): # type: (...) -> WPSExecution """ Run :func:`owslib.wps.WPSExecution.checkStatus` with additional exception handling. :param location: job URL or file path where to look for job status. :param response: WPS response document of job status. :param sleep_secs: number of seconds to sleep before returning control to the caller. :param verify: flag to enable SSL verification. :param settings: application settings to retrieve any additional request parameters as applicable. :returns: OWSLib.wps.WPSExecution object. """ def _retry_file(): # type: () -> str LOGGER.warning( "Failed retrieving WPS status-location, attempting with local file." ) out_path = get_wps_local_status_location(location, settings) if not out_path: raise HTTPNotFound( f"Could not find file resource from [{location}].") LOGGER.info("Resolved WPS status-location using local file reference.") with open(out_path, mode="r", encoding="utf-8") as f: return f.read() execution = WPSExecution() if response: LOGGER.debug("Retrieving WPS status from XML response document...") xml_data = response elif location: xml_resp = HTTPNotFound() xml_data = None try: LOGGER.debug( "Attempt to retrieve WPS status-location from URL [%s]...", location) xml_resp = request_extra("get", location, verify=verify, settings=settings) xml_data = xml_resp.content except Exception as ex: LOGGER.debug( "Got exception during get status: [%r]. Will retry with local reference.", ex) if xml_resp.status_code != HTTPOk.code: LOGGER.debug( "WPS XML status not found: [%r]. Retrying with local reference.", xml_data) xml_data = _retry_file() else: raise Exception( "Missing status-location URL/file reference or response with XML object." ) if isinstance(xml_data, str): xml_data = xml_data.encode("utf8", errors="ignore") execution.checkStatus(response=xml_data, sleepSecs=sleep_secs) if execution.response is None: raise Exception("Missing response, cannot check status.") if not isinstance(execution.response, xml_util.XML): execution.response = xml_util.fromstring(execution.response) return execution
def test_wps_checkStatus(): execution = WPSExecution() xml = open(resource_file('wps_PMLExecuteResponse5.xml'), 'rb').read() execution.checkStatus(response=xml) assert execution.isSucceded() assert execution.creationTime == '2011-11-08T21:36:55Z'
def wps_execute(self, version, accept): wps_url = get_wps_url(self.settings) if version == "1.0.0": test_content = "Test file in Docker - WPS KVP" wps_method = "GET" elif version == "2.0.0": test_content = "Test file in Docker - WPS XML" wps_method = "POST" else: raise ValueError("Invalid WPS version: {}".format(version)) test_content += " {} request - Accept {}".format(wps_method, accept.split("/")[-1].upper()) with contextlib.ExitStack() as stack_exec: # setup dir_name = tempfile.gettempdir() tmp_file = stack_exec.enter_context(tempfile.NamedTemporaryFile(dir=dir_name, mode="w", suffix=".txt")) tmp_file.write(test_content) tmp_file.seek(0) for mock_exec in mocked_execute_process(): stack_exec.enter_context(mock_exec) # execute if version == "1.0.0": wps_inputs = ["file={}@mimeType={}".format(tmp_file.name, CONTENT_TYPE_TEXT_PLAIN)] wps_params = { "service": "WPS", "request": "Execute", "version": version, "identifier": self.process_id, "DataInputs": wps_inputs, } wps_headers = {"Accept": accept} wps_data = None else: wps_inputs = [("file", ComplexDataInput(tmp_file.name, mimeType=CONTENT_TYPE_TEXT_PLAIN))] wps_outputs = [(self.out_key, True)] # as reference wps_exec = WPSExecution(version=version, url=wps_url) wps_req = wps_exec.buildRequest(self.process_id, wps_inputs, wps_outputs) wps_data = xml_util.tostring(wps_req) wps_headers = {"Accept": accept, "Content-Type": CONTENT_TYPE_APP_XML} wps_params = None resp = mocked_sub_requests(self.app, wps_method, wps_url, params=wps_params, data=wps_data, headers=wps_headers, only_local=True) assert resp.status_code in [200, 201], ( "Failed with: [{}]\nTest: [{}]\nReason:\n{}".format(resp.status_code, test_content, resp.text) ) # parse response status if accept == CONTENT_TYPE_APP_XML: assert resp.content_type in CONTENT_TYPE_ANY_XML, test_content xml_body = xml_util.fromstring(str2bytes(resp.text)) status_url = xml_body.get("statusLocation") job_id = status_url.split("/")[-1].split(".")[0] elif accept == CONTENT_TYPE_APP_JSON: assert resp.content_type == CONTENT_TYPE_APP_JSON, test_content status_url = resp.json["location"] job_id = resp.json["jobID"] assert status_url assert job_id if accept == CONTENT_TYPE_APP_XML: wps_out_url = self.settings["weaver.wps_output_url"] weaver_url = self.settings["weaver.url"] assert status_url == f"{wps_out_url}/{job_id}.xml", "Status URL should be XML file for WPS-1 request" # remap to employ JSON monitor method (could be done with XML parsing otherwise) status_url = f"{weaver_url}/jobs/{job_id}" # job monitoring results = self.monitor_job(status_url) outputs = self.get_outputs(status_url) # validate XML status is updated accordingly wps_xml_status = os.path.join(self.settings["weaver.wps_output_dir"], job_id + ".xml") assert os.path.isfile(wps_xml_status) with open(wps_xml_status, "r") as status_file: assert "ProcessSucceeded" in status_file.read() self.validate_outputs(job_id, results, outputs, test_content)