def test_stacktrace_html(self): """Stack traces can be caught and rendered as html """ # This is about general exception handling, so ok to use catch-all # pylint: disable=W0703 try: bbox_intersection('aoeu', 'oaeu', []) except Exception, e: # Display message and traceback message = get_error_message(e) # print message message = message.to_text() self.assertIn(str(e), message) self.assertIn('line', message) self.assertIn('file', message) message = get_error_message(e) message = message.to_html() assert str(e) in message message = message.decode('string_escape') control_file_path = test_data_path( 'control', 'files', 'test-stacktrace-html.txt') expected_results = open(control_file_path).read().replace('\n', '') self.assertIn(expected_results, message)
def save_metadata(self): """Save metadata based on the field mapping state.""" metadata = self.field_mapping_widget.get_field_mapping() for key, value in metadata['fields'].items(): # Delete the key if it's set to None if key in self.metadata['inasafe_default_values']: self.metadata['inasafe_default_values'].pop(key) if value is None or value == []: if key in self.metadata['inasafe_fields']: self.metadata['inasafe_fields'].pop(key) else: self.metadata['inasafe_fields'][key] = value for key, value in metadata['values'].items(): # Delete the key if it's set to None if key in self.metadata['inasafe_fields']: self.metadata['inasafe_fields'].pop(key) if value is None: if key in self.metadata['inasafe_default_values']: self.metadata['inasafe_default_values'].pop(key) else: self.metadata['inasafe_default_values'][key] = value # Save metadata try: self.keyword_io.write_keywords( layer=self.layer, keywords=self.metadata) except InaSAFEError, e: error_message = get_error_message(e) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, self.tr('InaSAFE'), ((self.tr( 'An error was encountered when saving the following ' 'keywords:\n %s') % error_message.to_html())))
def save_current_keywords(self): """Save keywords to the layer. It will write out the keywords for the current layer. This method is based on the KeywordsDialog class. """ current_keywords = self.get_keywords() try: self.keyword_io.write_keywords(layer=self.layer, keywords=current_keywords) except InaSAFEError as e: error_message = get_error_message(e) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, tr('InaSAFE'), tr('An error was encountered when saving the following ' 'keywords:\n {error_message}').format( error_message=error_message.to_html())) if self.dock is not None: # noinspection PyUnresolvedReferences self.dock.get_layers() # Save default value to QSetting if current_keywords.get('inasafe_default_values'): for key, value in (list( current_keywords['inasafe_default_values'].items())): set_inasafe_default_value_qsetting(self.setting, RECENT, key, value)
def accept(self): """Automatic slot executed when the ok button is pressed. It will write out the keywords for the layer that is active. """ self.apply_changes() keywords = self.get_keywords() # If it's postprocessing layer, we need to check if age ratio is valid if self.radPostprocessing.isChecked(): valid_age_ratio, sum_age_ratios = self.age_ratios_are_valid( keywords) if not valid_age_ratio: message = self.tr( 'The sum of age ratios is %s which exceeds 1. Please ' 'adjust the age ration defaults so that their cumulative ' 'value is not greater than 1.' % sum_age_ratios) if not self.test: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning(self, self.tr('InaSAFE'), message) return try: self.keyword_io.write_keywords(layer=self.layer, keywords=keywords) except InaSAFEError, e: error_message = get_error_message(e) message = self.tr( 'An error was encountered when saving the keywords:\n' '%s' % error_message.to_html()) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning(self, self.tr('InaSAFE'), message)
def accept(self): """Automatic slot executed when the ok button is pressed. It will write out the keywords for the layer that is active. """ self.apply_changes() keywords = self.get_keywords() # If it's postprocessing layer, we need to check if age ratio is valid if self.radPostprocessing.isChecked(): valid_age_ratio, sum_age_ratios = self.age_ratios_are_valid( keywords) if not valid_age_ratio: message = self.tr( 'The sum of age ratios is %s which exceeds 1. Please ' 'adjust the age ration defaults so that their cumulative ' 'value is not greater than 1.' % sum_age_ratios) if not self.test: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning( self, self.tr('InaSAFE'), message) return try: self.keyword_io.write_keywords(layer=self.layer, keywords=keywords) except InaSAFEError, e: error_message = get_error_message(e) message = self.tr( 'An error was encountered when saving the keywords:\n' '%s' % error_message.to_html()) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning(self, self.tr('InaSAFE'), message)
def save_current_keywords(self): """Save keywords to the layer. It will write out the keywords for the current layer. This method is based on the KeywordsDialog class. """ current_keywords = self.get_keywords() try: self.keyword_io.write_keywords( layer=self.layer, keywords=current_keywords) except InaSAFEError as e: error_message = get_error_message(e) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, tr('InaSAFE'), tr('An error was encountered when saving the following ' 'keywords:\n {error_message}').format( error_message=error_message.to_html())) if self.dock is not None: # noinspection PyUnresolvedReferences self.dock.get_layers() # Save default value to QSetting if current_keywords.get('inasafe_default_values'): for key, value in ( list(current_keywords['inasafe_default_values'].items())): set_inasafe_default_value_qsetting( self.setting, RECENT, key, value)
def print_map_to_pdf(self, impact_report): """Print map to PDF given MapReport instance. :param impact_report: Impact Report instance that is ready to print :type impact_report: ImpactReport """ impact_report.setup_composition() # Get Filename map_title = impact_report.map_title if map_title is not None: default_file_name = map_title + '.pdf' default_file_name = default_file_name.replace(' ', '_') else: self.show_error_message(self.tr('Keyword "map_title" not found.')) return # Get output path # noinspection PyCallByClass,PyTypeChecker output_path = QtGui.QFileDialog.getSaveFileName( self.parent, self.tr('Write to PDF'), os.path.join(temp_dir(), default_file_name), self.tr('Pdf File (*.pdf)')) output_path = str(output_path) if output_path is None or output_path == '': self.show_dynamic_message( self, m.Message(m.Heading(self.tr('Map Creator'), **WARNING_STYLE), m.Text(self.tr('Printing cancelled!')))) return try: map_pdf_path, table_pdf_path = impact_report.print_to_pdf( output_path) # Make sure the file paths can wrap nicely: wrapped_map_path = map_pdf_path.replace(os.sep, '<wbr>' + os.sep) wrapped_table_path = table_pdf_path.replace( os.sep, '<wbr>' + os.sep) status = m.Message( m.Heading(self.tr('Map Creator'), **INFO_STYLE), m.Paragraph( self. tr('Your PDF was created....opening using the default PDF ' 'viewer on your system. The generated pdfs were saved ' 'as:')), m.Paragraph(wrapped_map_path), m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) self.show_dynamic_message(self, status) except TemplateLoadingError, e: self.show_error_message(get_error_message(e))
def fake_error(self): """Make a fake error (helper for other tests) :returns: Contents of the message viewer as string and with newlines stripped off. :rtype : str """ e = Exception() context = 'Something went wrong' message = get_error_message(e, context=context) self.message_viewer.error_message_event(None, message) text = self.message_viewer.page_to_text().replace('\n', '') return text
def test_issue157(self): """Verify that we get the error class name back - issue #157 .. seealso:: https://github.com/AIFDR/inasafe/issues/121 """ try: bbox_intersection('aoeu', 'oaeu', []) except BoundingBoxError, e: message = get_error_message(e) myString = 'BoundingBoxError' assert myString in message.to_text(), message myString = 'Western boundary' assert myString in message.to_text(), message
def save_current_keywords(self): """Save keywords to the layer. It will write out the keywords for the current layer. This method is based on the KeywordsDialog class. """ current_keywords = self.get_keywords() try: self.keyword_io.write_keywords(layer=self.layer, keywords=current_keywords) except InaSAFEError, e: error_message = get_error_message(e) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning( self, self.tr('InaSAFE'), ((self.tr('An error was encountered when saving the following ' 'keywords:\n %s') % error_message.to_html())))
def save_current_keywords(self): """Save keywords to the layer. It will write out the keywords for the current layer. This method is based on the KeywordsDialog class. """ current_keywords = self.get_keywords() try: self.keyword_io.write_keywords( layer=self.layer, keywords=current_keywords) except InaSAFEError, e: error_message = get_error_message(e) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QMessageBox.warning( self, self.tr('InaSAFE'), ((self.tr( 'An error was encountered when saving the following ' 'keywords:\n %s') % error_message.to_html())))
def analysis_error(self, exception, message): """A helper to spawn an error and halt processing. An exception will be logged, busy status removed and a message displayed. .. note:: Copied from the dock :param message: an ErrorMessage to display :type message: ErrorMessage, Message :param exception: An exception that was raised :type exception: Exception """ self.hide_busy() LOGGER.exception(message) message = get_error_message(exception, context=message) self.show_error_message(message) self.analysisDone.emit(False)
def analysis_error(sender, exception, message): """A helper to spawn an error and halt processing. An exception will be logged, busy status removed and a message displayed. .. versionadded:: 3.3 :param sender: The sender. :type sender: object :param message: an ErrorMessage to display :type message: ErrorMessage, Message :param exception: An exception that was raised :type exception: Exception """ LOGGER.exception(message) message = get_error_message(exception, context=message) send_error_message(sender, message)
'viewer on your system. The generated pdfs were saved ' 'as:')), m.Paragraph(wrapped_map_path), m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) self.show_dynamic_message(self, status) except TemplateLoadingError, e: self.show_error_message(get_error_message(e)) except Exception, e: # pylint: disable=broad-except self.show_error_message(get_error_message(e)) def open_map_in_composer(self, impact_report): """Open map in composer given MapReport instance. ..note:: (AG) See https://github.com/AIFDR/inasafe/issues/911. We need to set the composition to the composer before loading the template. :param impact_report: Impact Report to be opened in composer. :type impact_report: ImpactReport """ impact_report.setup_composition() self.composer = self.iface.createNewComposer() self.composer.setComposition(impact_report.composition) impact_report.load_template()
m.Paragraph(wrapped_map_path), m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) self.show_dynamic_message(self, status) except TemplateLoadingError, e: self.show_error_message(get_error_message(e)) except Exception, e: # pylint: disable=broad-except self.show_error_message(get_error_message(e)) def open_map_in_composer(self, impact_report): """Open map in composer given MapReport instance. ..note:: (AG) See https://github.com/AIFDR/inasafe/issues/911. We need to set the composition to the composer before loading the template. :param impact_report: Impact Report to be opened in composer. :type impact_report: ImpactReport """ impact_report.setup_composition() self.composer = self.iface.createNewComposer() self.composer.setComposition(impact_report.composition) impact_report.load_template()
m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) # noinspection PyTypeChecker self.show_dynamic_message(self, status) except TemplateLoadingError, e: send_error_message(self, get_error_message(e)) except Exception, e: # pylint: disable=broad-except send_error_message(self, get_error_message(e)) def open_map_in_composer(self, impact_report): """Open map in composer given MapReport instance. ..note:: (AG) See https://github.com/AIFDR/inasafe/issues/911. We need to set the composition to the composer before loading the template. :param impact_report: Impact Report to be opened in composer. :type impact_report: ImpactReport """ impact_report.setup_composition() self.composer = self.iface.createNewComposer() self.composer.setComposition(impact_report.composition) impact_report.load_template()
def accept(self): """Launch the multi exposure analysis.""" if not isinstance(self._multi_exposure_if, MultiExposureImpactFunction): # This should not happen as the "accept" button must be disabled if # the impact function is not ready. return ANALYSIS_FAILED_BAD_CODE, None self.tab_widget.setCurrentIndex(2) self.set_enabled_buttons(False) enable_busy_cursor() try: code, message, exposure = self._multi_exposure_if.run() message = basestring_to_message(message) if code == ANALYSIS_FAILED_BAD_INPUT: LOGGER.warning( tr('The impact function could not run because of the inputs.' )) send_error_message(self, message) LOGGER.warning(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return code, message elif code == ANALYSIS_FAILED_BAD_CODE: LOGGER.warning( tr('The impact function could not run because of a bug.')) LOGGER.exception(message.to_text()) send_error_message(self, message) disable_busy_cursor() self.set_enabled_buttons(True) return code, message if setting('generate_report', True, bool): LOGGER.info( 'Reports are going to be generated for the multiexposure.') # Report for the multi exposure report = [standard_multi_exposure_impact_report_metadata_html] error_code, message = ( self._multi_exposure_if.generate_report(report)) message = basestring_to_message(message) if error_code == ImpactReport.REPORT_GENERATION_FAILED: LOGGER.warning('The impact report could not be generated.') send_error_message(self, message) LOGGER.exception(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return error_code, message else: LOGGER.warning( 'Reports are not generated because of your settings.') display_warning_message_bar( tr('Reports'), tr('Reports are not going to be generated because of your ' 'InaSAFE settings.'), duration=10, iface_object=self.iface) # We always create the multi exposure group because we need # reports to be generated. root = QgsProject.instance().layerTreeRoot() if len(self.ordered_expected_layers()) == 0: group_analysis = root.insertGroup(0, self._multi_exposure_if.name) group_analysis.setItemVisibilityChecked(True) group_analysis.setCustomProperty(MULTI_EXPOSURE_ANALYSIS_FLAG, True) for layer in self._multi_exposure_if.outputs: QgsProject.instance().addMapLayer(layer, False) layer_node = group_analysis.addLayer(layer) layer_node.setItemVisibilityChecked(False) # set layer title if any try: title = layer.keywords['title'] if qgis_version() >= 21800: layer.setName(title) else: layer.setLayerName(title) except KeyError: pass for analysis in self._multi_exposure_if.impact_functions: detailed_group = group_analysis.insertGroup( 0, analysis.name) detailed_group.setItemVisibilityChecked(True) add_impact_layers_to_canvas(analysis, group=detailed_group) if self.iface: self.iface.setActiveLayer( self._multi_exposure_if.analysis_impacted) else: add_layers_to_canvas_with_custom_orders( self.ordered_expected_layers(), self._multi_exposure_if, self.iface) if setting('generate_report', True, bool): LOGGER.info( 'Reports are going to be generated for each single ' 'exposure.') # Report for the single exposure with hazard for analysis in self._multi_exposure_if.impact_functions: # we only want to generate non pdf/qpt report html_components = [standard_impact_report_metadata_html] error_code, message = ( analysis.generate_report(html_components)) message = basestring_to_message(message) if error_code == (ImpactReport.REPORT_GENERATION_FAILED): LOGGER.info( 'The impact report could not be generated.') send_error_message(self, message) LOGGER.info(message.to_text()) disable_busy_cursor() self.set_enabled_buttons(True) return error_code, message else: LOGGER.info( 'Reports are not generated because of your settings.') display_warning_message_bar( tr('Reports'), tr('Reports are not going to be generated because of your ' 'InaSAFE settings.'), duration=10, iface_object=self.iface) # If zoom to impact is enabled if setting('setZoomToImpactFlag', expected_type=bool): self.iface.zoomToActiveLayer() # If hide exposure layers if setting('setHideExposureFlag', expected_type=bool): treeroot = QgsProject.instance().layerTreeRoot() for combo in list(self.combos_exposures.values()): layer = layer_from_combo(combo) if layer is not None: treelayer = treeroot.findLayer(layer.id()) if treelayer: treelayer.setItemVisibilityChecked(False) # Set last analysis extent self._extent.set_last_analysis_extent( self._multi_exposure_if.analysis_extent, self._multi_exposure_if.crs) self.done(QDialog.Accepted) except Exception as e: error_message = get_error_message(e) send_error_message(self, error_message) LOGGER.exception(e) LOGGER.debug(error_message.to_text()) finally: disable_busy_cursor() self.set_enabled_buttons(True)
def clip_by_extent(layer, extent): """Clip a raster using a bounding box using processing. Issue https://github.com/inasafe/inasafe/issues/3183 :param layer: The layer to clip. :type layer: QgsRasterLayer :param extent: The extent. :type extent: QgsRectangle :return: Clipped layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ parameters = dict() # noinspection PyBroadException try: output_layer_name = quick_clip_steps['output_layer_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] output_raster = unique_filename(suffix='.tif', dir=temp_dir()) # We make one pixel size buffer on the extent to cover every pixels. # See https://github.com/inasafe/inasafe/issues/3655 pixel_size_x = layer.rasterUnitsPerPixelX() pixel_size_y = layer.rasterUnitsPerPixelY() buffer_size = max(pixel_size_x, pixel_size_y) extent = extent.buffered(buffer_size) if is_raster_y_inverted(layer): # The raster is Y inverted. We need to switch Y min and Y max. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMaximum()), str(extent.yMinimum()) ] else: # The raster is normal. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMinimum()), str(extent.yMaximum()) ] # These values are all from the processing algorithm. # https://github.com/qgis/QGIS/blob/master/python/plugins/processing/ # algs/gdal/ClipByExtent.py # Please read the file to know these parameters. parameters['INPUT'] = layer.source() parameters['NO_DATA'] = '' parameters['PROJWIN'] = ','.join(bbox) parameters['DATA_TYPE'] = 5 parameters['COMPRESS'] = 4 parameters['JPEGCOMPRESSION'] = 75 parameters['ZLEVEL'] = 6 parameters['PREDICTOR'] = 1 parameters['TILED'] = False parameters['BIGTIFF'] = 0 parameters['TFW'] = False parameters['EXTRA'] = '' parameters['OUTPUT'] = output_raster initialize_processing() feedback = create_processing_feedback() context = create_processing_context(feedback=feedback) result = processing.run( "gdal:cliprasterbyextent", parameters, context=context) if result is None: raise ProcessingInstallationError clipped = QgsRasterLayer(result['OUTPUT'], output_layer_name) # We transfer keywords to the output. clipped.keywords = layer.keywords.copy() clipped.keywords['title'] = output_layer_name check_layer(clipped) except Exception as e: # This step clip_raster_by_extent was nice to speedup the analysis. # As we got an exception because the layer is invalid, we are not going # to stop the analysis. We will return the original raster layer. # It will take more processing time until we clip the vector layer. # Check https://github.com/inasafe/inasafe/issues/4026 why we got some # exceptions with this step. LOGGER.exception(parameters) LOGGER.exception( 'Error from QGIS clip raster by extent. Please check the QGIS ' 'logs too !') LOGGER.info( 'Even if we got an exception, we are continuing the analysis. The ' 'layer was not clipped.') LOGGER.exception(str(e)) LOGGER.exception(get_error_message(e).to_text()) clipped = layer return clipped
def print_map_to_pdf(self, impact_report): """Print map to PDF given MapReport instance. :param impact_report: Impact Report instance that is ready to print :type impact_report: ImpactReport """ impact_report.setup_composition() # Get Filename map_title = impact_report.map_title if map_title is not None: default_file_name = map_title + '.pdf' default_file_name = default_file_name.replace(' ', '_') else: self.show_error_message( self.tr('Keyword "map_title" not found.')) return # Get output path # noinspection PyCallByClass,PyTypeChecker output_path = QtGui.QFileDialog.getSaveFileName( self.parent, self.tr('Write to PDF'), os.path.join(temp_dir(), default_file_name), self.tr('Pdf File (*.pdf)')) output_path = str(output_path) if output_path is None or output_path == '': self.show_dynamic_message( self, m.Message( m.Heading(self.tr('Map Creator'), **WARNING_STYLE), m.Text(self.tr('Printing cancelled!')))) return try: map_pdf_path, table_pdf_path = impact_report.print_to_pdf( output_path) # Make sure the file paths can wrap nicely: wrapped_map_path = map_pdf_path.replace(os.sep, '<wbr>' + os.sep) wrapped_table_path = table_pdf_path.replace(os.sep, '<wbr>' + os.sep) status = m.Message( m.Heading(self.tr('Map Creator'), **INFO_STYLE), m.Paragraph(self.tr( 'Your PDF was created....opening using the default PDF ' 'viewer on your system. The generated pdfs were saved ' 'as:')), m.Paragraph(wrapped_map_path), m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) self.show_dynamic_message(self, status) except TemplateLoadingError, e: self.show_error_message(get_error_message(e))
def clip_by_extent(layer, extent, callback=None): """Clip a raster using a bounding box using processing. Issue https://github.com/inasafe/inasafe/issues/3183 :param layer: The layer to reproject. :type layer: QgsRasterLayer :param extent: The extent. :type extent: QgsRectangle :param callback: A function to all to indicate progress. The function should accept params 'current' (int) and 'maximum' (int). Defaults to None. :type callback: function :return: Reprojected memory layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ parameters = dict() # noinspection PyBroadException try: output_layer_name = quick_clip_steps['output_layer_name'] processing_step = quick_clip_steps['step_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] output_raster = unique_filename(dir=temp_dir()) # We make one pixel size buffer on the extent to cover every pixels. # See https://github.com/inasafe/inasafe/issues/3655 pixel_size_x = layer.rasterUnitsPerPixelX() pixel_size_y = layer.rasterUnitsPerPixelY() buffer_size = max(pixel_size_x, pixel_size_y) extent = extent.buffer(buffer_size) if is_raster_y_inverted(layer): # The raster is Y inverted. We need to switch Y min and Y max. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMaximum()), str(extent.yMinimum()) ] else: # The raster is normal. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMinimum()), str(extent.yMaximum()) ] # These values are all from the processing algorithm. # https://github.com/qgis/QGIS/blob/master/python/plugins/processing/ # algs/gdal/ClipByExtent.py # Please read the file to know these parameters. parameters['INPUT'] = layer.source() parameters['NO_DATA'] = '' parameters['PROJWIN'] = ','.join(bbox) parameters['RTYPE'] = 5 parameters['COMPRESS'] = 4 parameters['JPEGCOMPRESSION'] = 75 parameters['ZLEVEL'] = 6 parameters['PREDICTOR'] = 1 parameters['TILED'] = False parameters['BIGTIFF'] = 0 parameters['TFW'] = False parameters['EXTRA'] = '' parameters['OUTPUT'] = output_raster result = processing.runalg("gdalogr:cliprasterbyextent", parameters) if result is None: raise ProcessingInstallationError clipped = QgsRasterLayer(result['OUTPUT'], output_layer_name) # We transfer keywords to the output. clipped.keywords = layer.keywords.copy() clipped.keywords['title'] = output_layer_name check_layer(clipped) except Exception as e: # This step clip_raster_by_extent was nice to speedup the analysis. # As we got an exception because the layer is invalid, we are not going # to stop the analysis. We will return the original raster layer. # It will take more processing time until we clip the vector layer. # Check https://github.com/inasafe/inasafe/issues/4026 why we got some # exceptions with this step. LOGGER.exception(parameters) LOGGER.exception( 'Error from QGIS clip raster by extent. Please check the QGIS ' 'logs too !') LOGGER.info( 'Even if we got an exception, we are continuing the analysis. The ' 'layer is not clip.') LOGGER.exception(str(e)) LOGGER.exception(get_error_message(e).to_text()) clipped = layer return clipped
def process_components(self): """Process context for each component and a given template. :returns: Tuple of error code and message :type: tuple .. versionadded:: 4.0 """ message = m.Message() warning_heading = m.Heading( tr('Report Generation issue'), **WARNING_STYLE) message.add(warning_heading) failed_extract_context = m.Heading(tr( 'Failed to extract context'), **WARNING_STYLE) failed_render_context = m.Heading(tr( 'Failed to render context'), **WARNING_STYLE) failed_find_extractor = m.Heading(tr( 'Failed to load extractor method'), **WARNING_STYLE) failed_find_renderer = m.Heading(tr( 'Failed to load renderer method'), **WARNING_STYLE) generation_error_code = self.REPORT_GENERATION_SUCCESS for component in self.metadata.components: # load extractors try: if not component.context: if callable(component.extractor): _extractor_method = component.extractor else: _package_name = ( '%(report-key)s.extractors.%(component-key)s') _package_name %= { 'report-key': self.metadata.key, 'component-key': component.key } # replace dash with underscores _package_name = _package_name.replace('-', '_') _extractor_path = os.path.join( self.metadata.template_folder, component.extractor ) _module = imp.load_source( _package_name, _extractor_path) _extractor_method = getattr(_module, 'extractor') else: LOGGER.info('Predefined context. Extractor not needed.') except Exception as e: # pylint: disable=broad-except generation_error_code = self.REPORT_GENERATION_FAILED LOGGER.info(e) if self.impact_function.debug_mode: raise else: message.add(failed_find_extractor) message.add(component.info) message.add(get_error_message(e)) continue # method signature: # - this ImpactReport # - this component try: if not component.context: context = _extractor_method(self, component) component.context = context else: LOGGER.info('Using predefined context.') except Exception as e: # pylint: disable=broad-except generation_error_code = self.REPORT_GENERATION_FAILED LOGGER.info(e) if self.impact_function.debug_mode: raise else: message.add(failed_extract_context) message.add(get_error_message(e)) continue try: # load processor if callable(component.processor): _renderer = component.processor else: _package_name = '%(report-key)s.renderer.%(component-key)s' _package_name %= { 'report-key': self.metadata.key, 'component-key': component.key } # replace dash with underscores _package_name = _package_name.replace('-', '_') _renderer_path = os.path.join( self.metadata.template_folder, component.processor ) _module = imp.load_source(_package_name, _renderer_path) _renderer = getattr(_module, 'renderer') except Exception as e: # pylint: disable=broad-except generation_error_code = self.REPORT_GENERATION_FAILED LOGGER.info(e) if self.impact_function.debug_mode: raise else: message.add(failed_find_renderer) message.add(component.info) message.add(get_error_message(e)) continue # method signature: # - this ImpactReport # - this component if component.context: try: output = _renderer(self, component) output_path = self.component_absolute_output_path( component.key) if isinstance(output_path, dict): try: dirname = os.path.dirname(output_path.get('doc')) except: dirname = os.path.dirname(output_path.get('map')) else: dirname = os.path.dirname(output_path) if component.resources: for resource in component.resources: target_resource = os.path.basename(resource) target_dir = os.path.join( dirname, 'resources', target_resource) # copy here shutil.copytree(resource, target_dir) component.output = output except Exception as e: # pylint: disable=broad-except generation_error_code = self.REPORT_GENERATION_FAILED LOGGER.info(e) if self.impact_function.debug_mode: raise else: message.add(failed_render_context) message.add(get_error_message(e)) continue return generation_error_code, message