def printToPdf(self, theHtml, theFilename=None): """Render an html snippet into the printer, paginating as needed. Args: * theHtml: str A string containing an html snippet. It will have a header and footer appended to it in order to make it a valid html document. The header will also apply the bootstrap theme to the document. * theFilename: str String containing a pdf file path that the output will be written to. Returns: str: The file path of the output pdf (which is the same as the theFilename parameter if it was specified. Raises: None """ LOGGER.info('InaSAFE Map printToPdf called') if theFilename is None: myHtmlPdfPath = unique_filename(prefix='table', suffix='.pdf', dir=temp_dir('work')) else: # We need to cast to python string in case we receive a QString myHtmlPdfPath = str(theFilename) self.printer = setupPrinter(myHtmlPdfPath) self.loadAndWait(theHtmlSnippet=theHtml) self.webView.print_(self.printer) return myHtmlPdfPath
def printImpactTable(self, theKeywords, theFilename=None): """High level table generator to print layer keywords. It gets the summary and impact table from a QgsMapLayer's keywords and renders to pdf, returning the resulting PDF file path. Args: theKeywords: dic containing impact layer keywords (required) Returns: str: Path to generated pdf file. Raises: None """ myFilePath = theFilename if theFilename is None: myFilePath = unique_filename(suffix='.pdf', dir=temp_dir()) try: mySummaryTable = theKeywords['impact_summary'] except KeyError: mySummaryTable = None myAttributionTable = impactLayerAttribution(theKeywords) try: myFullTable = theKeywords['impact_table'] except KeyError: myFullTable = None try: myAggregationTable = theKeywords['postprocessing_report'] except KeyError: myAggregationTable = None myHtml = '' if mySummaryTable != myFullTable and mySummaryTable is not None: myHtml = '<h2>%s</h2>' % self.tr('Summary Table') myHtml += mySummaryTable if myAggregationTable is not None: myHtml += myAggregationTable if myAttributionTable is not None: myHtml += myAttributionTable myHtml += '<h2>%s</h2>' % self.tr('Detailed Table') myHtml += myFullTable else: if myAggregationTable is not None: myHtml = myAggregationTable if myFullTable is not None: myHtml += myFullTable if myAttributionTable is not None: myHtml += myAttributionTable # myNewFilePath should be the same as myFilePath myNewFilePath = self.printToPdf(myHtml, myFilePath) return myNewFilePath
def test_Converting(self): """Test converting a file """ myDialog = ConverterDialog(PARENT) myDialog.test_mode = True myDialog.cBDefaultOutputLocation.setEnabled(False) my_grid_path = os.path.join(TESTDATA, "grid.xml") my_output_raster = unique_filename(prefix="result_grid", suffix=".tif", dir=temp_dir("test")) myDialog.cBLoadLayer.setEnabled(True) myDialog.leInputPath.setText(my_grid_path) myDialog.leOutputPath.setText(my_output_raster) myButton = myDialog.buttonBox.button(QDialogButtonBox.Ok) QTest.mouseClick(myButton, Qt.LeftButton) assert os.path.exists(my_output_raster), "Raster is not created"
def test_writeReadKeywordFromUri(self): """Test we can set and get keywords for a non local datasource""" myHandle, myFilename = tempfile.mkstemp('.db', 'keywords_', temp_dir()) # Ensure the file is deleted before we try to write to it # fixes windows specific issue where you get a message like this # ERROR 1: c:\temp\inasafe\clip_jpxjnt.shp is not a directory. # This is because mkstemp creates the file handle and leaves # the file open. os.close(myHandle) os.remove(myFilename) myExpectedKeywords = { 'category': 'exposure', 'datatype': 'itb', 'subcategory': 'building' } # SQL insert test # On first write schema is empty and there is no matching hash self.keywordIO.setKeywordDbPath(myFilename) self.keywordIO.writeKeywordsForUri(PG_URI, myExpectedKeywords) # SQL Update test # On second write schema is populated and we update matching hash myExpectedKeywords = { 'category': 'exposure', 'datatype': 'OSM', # <--note the change here! 'subcategory': 'building' } self.keywordIO.writeKeywordsForUri(PG_URI, myExpectedKeywords) # Test getting all keywords myKeywords = self.keywordIO.readKeywordFromUri(PG_URI) myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % ( myKeywords, myExpectedKeywords, myFilename) assert myKeywords == myExpectedKeywords, myMessage # Test getting just a single keyword myKeyword = self.keywordIO.readKeywordFromUri(PG_URI, 'datatype') myExpectedKeyword = 'OSM' myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % ( myKeyword, myExpectedKeyword, myFilename) assert myKeyword == myExpectedKeyword, myMessage # Test deleting keywords actually does delete self.keywordIO.deleteKeywordsForUri(PG_URI) try: myKeyword = self.keywordIO.readKeywordFromUri(PG_URI, 'datatype') #if the above didnt cause an exception then bad myMessage = 'Expected a HashNotFoundError to be raised' assert myMessage except HashNotFoundError: #we expect this outcome so good! pass
def Xtest_Converting(self): """Test converting a file """ myDialog = ConverterDialog(PARENT) myDialog.test_mode = True myDialog.cBDefaultOutputLocation.setEnabled(False) my_grid_path = os.path.join(TESTDATA, 'grid.xml') my_output_raster = unique_filename(prefix='result_grid', suffix='.tif', dir=temp_dir('test')) myDialog.cBLoadLayer.setEnabled(True) myDialog.leInputPath.setText(my_grid_path) myDialog.leOutputPath.setText(my_output_raster) myButton = myDialog.buttonBox.button(QDialogButtonBox.Ok) QTest.mouseClick(myButton, Qt.LeftButton) assert os.path.exists(my_output_raster), 'Raster is not created'
def test_writeReadKeywordFromUri(self): """Test we can set and get keywords for a non local datasource""" myHandle, myFilename = tempfile.mkstemp('.db', 'keywords_', temp_dir()) # Ensure the file is deleted before we try to write to it # fixes windows specific issue where you get a message like this # ERROR 1: c:\temp\inasafe\clip_jpxjnt.shp is not a directory. # This is because mkstemp creates the file handle and leaves # the file open. os.close(myHandle) os.remove(myFilename) myExpectedKeywords = {'category': 'exposure', 'datatype': 'itb', 'subcategory': 'building'} # SQL insert test # On first write schema is empty and there is no matching hash self.keywordIO.setKeywordDbPath(myFilename) self.keywordIO.writeKeywordsForUri(PG_URI, myExpectedKeywords) # SQL Update test # On second write schema is populated and we update matching hash myExpectedKeywords = {'category': 'exposure', 'datatype': 'OSM', # <--note the change here! 'subcategory': 'building'} self.keywordIO.writeKeywordsForUri(PG_URI, myExpectedKeywords) # Test getting all keywords myKeywords = self.keywordIO.readKeywordFromUri(PG_URI) myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % ( myKeywords, myExpectedKeywords, myFilename) assert myKeywords == myExpectedKeywords, myMessage # Test getting just a single keyword myKeyword = self.keywordIO.readKeywordFromUri(PG_URI, 'datatype') myExpectedKeyword = 'OSM' myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % ( myKeyword, myExpectedKeyword, myFilename) assert myKeyword == myExpectedKeyword, myMessage # Test deleting keywords actually does delete self.keywordIO.deleteKeywordsForUri(PG_URI) try: myKeyword = self.keywordIO.readKeywordFromUri(PG_URI, 'datatype') #if the above didnt cause an exception then bad myMessage = 'Expected a HashNotFoundError to be raised' assert myMessage except HashNotFoundError: #we expect this outcome so good! pass
def setupLogger(): """Run once when the module is loaded and enable logging Args: None Returns: None Raises: None Borrowed heavily from this: http://docs.python.org/howto/logging-cookbook.html Use this to first initialise the logger (see safe/__init__.py):: from safe_qgis import utilities utilities.setupLogger() You would typically only need to do the above once ever as the safe modle is initialised early and will set up the logger globally so it is available to all packages / subpackages as shown below. In a module that wants to do logging then use this example as a guide to get the initialised logger instance:: # The LOGGER is intialised in utilities.py by init import logging LOGGER = logging.getLogger('InaSAFE') Now to log a message do:: LOGGER.debug('Some debug message') .. note:: The file logs are written to the inasafe user tmp dir e.g.: /tmp/inasafe/23-08-2012/timlinux/logs/inasafe.log """ myLogger = logging.getLogger('InaSAFE') myLogger.setLevel(logging.DEBUG) myDefaultHanderLevel = logging.DEBUG # create formatter that will be added to the handlers myFormatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') # create syslog handler which logs even debug messages # (ariel): Make this log to /var/log/safe.log instead of # /var/log/syslog # (Tim) Ole and I discussed this - we prefer to log into the # user's temporary working directory. myTempDir = temp_dir('logs') myFilename = os.path.join(myTempDir, 'inasafe.log') myFileHandler = logging.FileHandler(myFilename) myFileHandler.setLevel(myDefaultHanderLevel) # create console handler with a higher log level myConsoleHandler = logging.StreamHandler() myConsoleHandler.setLevel(logging.ERROR) myQgisHandler = QgsLogHandler() # TODO: User opt in before we enable email based logging. # Email handler for errors #myEmailServer = 'localhost' #myEmailServerPort = 25 #mySenderAddress = '*****@*****.**' #myRecipientAddresses = ['*****@*****.**'] #mySubject = 'Error' #myEmailHandler = logging.handlers.SMTPHandler( # (myEmailServer, myEmailServerPort), # mySenderAddress, # myRecipientAddresses, # mySubject) #myEmailHandler.setLevel(logging.ERROR) # Sentry handler - this is optional hence the localised import # It will only log if pip install raven. If raven is available # logging messages will be sent to http://sentry.linfiniti.com # We will log exceptions only there. Only if you have the env var # 'INSAFE_SENTRY=1' present (value can be anything) will this be enabled. if 'INASAFE_SENTRY' in os.environ: try: #pylint: disable=F0401 from raven.handlers.logging import SentryHandler from raven import Client #pylint: enable=F0401 myClient = Client('http://*****:*****@sentry.linfiniti.com/' '4') mySentryHandler = SentryHandler(myClient) mySentryHandler.setFormatter(myFormatter) mySentryHandler.setLevel(logging.ERROR) if addLoggingHanderOnce(myLogger, mySentryHandler): myLogger.debug('Sentry logging enabled') except ImportError: myLogger.debug('Sentry logging disabled') #Set formatters myFileHandler.setFormatter(myFormatter) myConsoleHandler.setFormatter(myFormatter) #myEmailHandler.setFormatter(myFormatter) myQgisHandler.setFormatter(myFormatter) # add the handlers to the logger addLoggingHanderOnce(myLogger, myFileHandler) addLoggingHanderOnce(myLogger, myConsoleHandler) #addLoggingHanderOnce(myLogger, myEmailHandler) addLoggingHanderOnce(myLogger, myQgisHandler)
def setupLogger(theLogFile=None, theSentryUrl=None): """Run once when the module is loaded and enable logging Args: * theLogFile: str - optional full path to a file to write logs to. * theSentryUrl: str - optional url to sentry api for remote logging. Defaults to http://c64a83978732474ea751d432ab943a6b :[email protected]/5 which is the sentry project for InaSAFE desktop. Returns: None Raises: None Borrowed heavily from this: http://docs.python.org/howto/logging-cookbook.html Use this to first initialise the logger (see safe/__init__.py):: from safe_qgis import utilities utilities.setupLogger() You would typically only need to do the above once ever as the safe modle is initialised early and will set up the logger globally so it is available to all packages / subpackages as shown below. In a module that wants to do logging then use this example as a guide to get the initialised logger instance:: # The LOGGER is intialised in utilities.py by init import logging LOGGER = logging.getLogger('InaSAFE') Now to log a message do:: LOGGER.debug('Some debug message') .. note:: The file logs are written to the inasafe user tmp dir e.g.: /tmp/inasafe/23-08-2012/timlinux/logs/inasafe.log """ myLogger = logging.getLogger('InaSAFE') myLogger.setLevel(logging.DEBUG) myDefaultHanderLevel = logging.DEBUG # create formatter that will be added to the handlers myFormatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') # create syslog handler which logs even debug messages # (ariel): Make this log to /var/log/safe.log instead of # /var/log/syslog # (Tim) Ole and I discussed this - we prefer to log into the # user's temporary working directory. myTempDir = temp_dir('logs') myFilename = os.path.join(myTempDir, 'inasafe.log') if theLogFile is None: myFileHandler = logging.FileHandler(myFilename) else: myFileHandler = logging.FileHandler(theLogFile) myFileHandler.setLevel(myDefaultHanderLevel) # create console handler with a higher log level myConsoleHandler = logging.StreamHandler() myConsoleHandler.setLevel(logging.INFO) myQGISHandler = QgsLogHandler() # Sentry handler - this is optional hence the localised import # It will only log if pip install raven. If raven is available # logging messages will be sent to http://sentry.linfiniti.com # We will log exceptions only there. You need to either: # * Set env var 'INSAFE_SENTRY=1' present (value can be anything) # * Enable the 'help improve InaSAFE by submitting errors to a remove # server' option in InaSAFE options dialog # before this will be enabled. mySettings = QtCore.QSettings() myFlag = mySettings.value('inasafe/useSentry', False).toBool() if 'INASAFE_SENTRY' in os.environ or myFlag: if theSentryUrl is None: myClient = Client( 'http://c64a83978732474ea751d432ab943a6b' ':[email protected]/5') else: myClient = Client(theSentryUrl) mySentryHandler = SentryHandler(myClient) mySentryHandler.setFormatter(myFormatter) mySentryHandler.setLevel(logging.ERROR) if addLoggingHanderOnce(myLogger, mySentryHandler): myLogger.debug('Sentry logging enabled') else: myLogger.debug('Sentry logging disabled') #Set formatters myFileHandler.setFormatter(myFormatter) myConsoleHandler.setFormatter(myFormatter) myQGISHandler.setFormatter(myFormatter) # add the handlers to the logger addLoggingHanderOnce(myLogger, myFileHandler) addLoggingHanderOnce(myLogger, myConsoleHandler) addLoggingHanderOnce(myLogger, myQGISHandler)