From 1c235e55e5264a6a562a17615ec6e8e66fe3779c Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Mon, 21 Aug 2023 10:48:02 +0200 Subject: [PATCH 1/2] Raise QGIS minimum version to 3.18 instead of 3.4 --- cadastre/cadastre_common_base.py | 16 ++++++---------- cadastre/cadastre_menu.py | 9 ++++----- cadastre/metadata.txt | 2 +- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/cadastre/cadastre_common_base.py b/cadastre/cadastre_common_base.py index 8bbcdfee..e6a38238 100644 --- a/cadastre/cadastre_common_base.py +++ b/cadastre/cadastre_common_base.py @@ -213,16 +213,12 @@ def getConnectorFromUri(connectionParams: Dict[str, str]) -> 'DBConnector': connectionParams['password'] ) - if Qgis.QGIS_VERSION_INT >= 31200: - # we need a fake DBPlugin object - # with connectionName and providerName methods - obj = QObject() - obj.connectionName = lambda: 'fake' - obj.providerName = lambda: 'postgres' - - connector = PostGisDBConnector(uri, obj) - else: - connector = PostGisDBConnector(uri) + # we need a fake DBPlugin object + # with connectionName and providerName methods + obj = QObject() + obj.connectionName = lambda: 'fake' + obj.providerName = lambda: 'postgres' + connector = PostGisDBConnector(uri, obj) if connectionParams['dbType'] == 'spatialite': uri.setConnection('', '', connectionParams['dbname'], '', '') diff --git a/cadastre/cadastre_menu.py b/cadastre/cadastre_menu.py index 27eaa54b..e60ab682 100644 --- a/cadastre/cadastre_menu.py +++ b/cadastre/cadastre_menu.py @@ -85,10 +85,9 @@ def initGui(self): main_icon = QIcon(os.path.join(plugin_dir, "icon.png")) # Open the online help - if Qgis.QGIS_VERSION_INT >= 31000: - self.help_action_about_menu = QAction(main_icon, 'Cadastre', self.iface.mainWindow()) - self.iface.pluginHelpMenu().addAction(self.help_action_about_menu) - self.help_action_about_menu.triggered.connect(self.open_help) + self.help_action_about_menu = QAction(main_icon, 'Cadastre', self.iface.mainWindow()) + self.iface.pluginHelpMenu().addAction(self.help_action_about_menu) + self.help_action_about_menu.triggered.connect(self.open_help) actions = { "import_action": ( @@ -520,7 +519,7 @@ def open_message_dialog(self): dialog.exec_() def unload(self): - if Qgis.QGIS_VERSION_INT >= 31000 and self.help_action_about_menu: + if self.help_action_about_menu: self.iface.pluginHelpMenu().removeAction(self.help_action_about_menu) del self.help_action_about_menu diff --git a/cadastre/metadata.txt b/cadastre/metadata.txt index 331c79a2..c41db1d0 100644 --- a/cadastre/metadata.txt +++ b/cadastre/metadata.txt @@ -2,7 +2,7 @@ name=cadastre -qgisMinimumVersion=3.4 +qgisMinimumVersion=3.18 qgisMaximumVersion=3.99 description=This plugins helps users to use French land registry data, called Cadastre, in QGIS. It is only useful in From c9e2b784f5e7f93557ff1475dfeff7feeaa1925b Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Mon, 21 Aug 2023 10:53:51 +0200 Subject: [PATCH 2/2] Follow up previous commit, raise to Python 3.6 minimum, for QGIS 3.18 --- cadastre/__init__.py | 1 - cadastre/cadastre_common_base.py | 4 +- cadastre/cadastre_export.py | 52 +++---- cadastre/cadastre_identify_parcelle.py | 1 - cadastre/cadastre_import.py | 144 +++++++++--------- cadastre/cadastre_loading.py | 29 ++-- cadastre/cadastre_menu.py | 7 +- cadastre/dialogs/about_dialog.py | 4 +- cadastre/dialogs/cadastre_export_dialog.py | 4 +- cadastre/dialogs/cadastre_load_dialog.py | 4 +- cadastre/dialogs/custom_qcompleter.py | 4 +- cadastre/dialogs/custom_qpush_button.py | 2 +- cadastre/dialogs/dialog_common.py | 20 +-- cadastre/dialogs/import_dialog.py | 26 ++-- cadastre/dialogs/message_dialog.py | 4 +- cadastre/dialogs/options_dialog.py | 20 +-- cadastre/dialogs/parcelle_dialog.py | 20 +-- cadastre/dialogs/search_dialog.py | 38 ++--- cadastre/edigeo_parser.py | 2 +- cadastre/getmultipolygonfromvec.py | 10 +- cadastre/infra/processing_doc.py | 2 +- cadastre/logger.py | 4 +- cadastre/processing/algorithms/config.py | 2 +- .../algorithms/edigeo_downloader.py | 22 +-- cadastre/scripts/pyogr/ogr2ogr.py | 11 +- cadastre/scripts/pyogr/ogrds.py | 2 +- cadastre/scripts/pyogr/ogrinfo.py | 20 +-- cadastre/server/cadastre_server.py | 4 +- cadastre/server/cadastre_service.py | 14 +- cadastre/tests/runner.py | 24 +-- cadastre/tools.py | 6 +- tests/conftest.py | 6 +- 32 files changed, 252 insertions(+), 261 deletions(-) diff --git a/cadastre/__init__.py b/cadastre/__init__.py index df187b8c..8058527f 100644 --- a/cadastre/__init__.py +++ b/cadastre/__init__.py @@ -20,7 +20,6 @@ ***************************************************************************/ This script initializes the plugin, making it known to QGIS. """ -from __future__ import absolute_import def classFactory(iface): diff --git a/cadastre/cadastre_common_base.py b/cadastre/cadastre_common_base.py index e6a38238..d438901d 100644 --- a/cadastre/cadastre_common_base.py +++ b/cadastre/cadastre_common_base.py @@ -174,7 +174,7 @@ def fetchDataFromSqlQuery(connector: 'DBConnector', except BaseError as e: ok = False QgsMessageLog.logMessage( - "Error while fetching data from database : {}".format(str(e.msg)), + f"Error while fetching data from database : {str(e.msg)}", "cadastre", Qgis.Critical ) @@ -232,7 +232,7 @@ def getConnectorFromUri(connectionParams: Dict[str, str]) -> 'DBConnector': connector = SpatiaLiteDBConnector(uri) except ConnectionError as e: QgsMessageLog.logMessage( - "Erreur lors de la récupération du fichier SQLite : {}".format(str(e)), + f"Erreur lors de la récupération du fichier SQLite : {str(e)}", 'cadastre', Qgis.Critical) diff --git a/cadastre/cadastre_export.py b/cadastre/cadastre_export.py index f57b5ad2..3cafe1a8 100644 --- a/cadastre/cadastre_export.py +++ b/cadastre/cadastre_export.py @@ -123,9 +123,9 @@ def __init__(self, project: QgsProject, layer: QgsMapLayer, etype: str, compteco # label for header2 if self.etype == 'proprietaire': - self.typeLabel = u'DE PROPRIÉTÉ' + self.typeLabel = 'DE PROPRIÉTÉ' else: - self.typeLabel = u'PARCELLAIRE' + self.typeLabel = 'PARCELLAIRE' self.layer = layer self.connectionParams = cadastre_common.getConnectionParameterFromDbLayer(self.layer) @@ -157,8 +157,8 @@ def set_composer_templates(self, compte_communal): 'type': 'sql', 'filter': 'comptecommunal', 'and': { - 'proprietaire': " AND comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND comptecommunal = '{}'".format(compte_communal), + 'proprietaire': f" AND comptecommunal = '{compte_communal}'", + 'parcelle': f" AND comptecommunal = '{compte_communal}'", }, 'sticky': True }, @@ -200,8 +200,8 @@ def set_composer_templates(self, compte_communal): 'keepContent': True, 'filter': 'comptecommunal', 'and': { - 'proprietaire': " AND l10.comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND p.parcelle = '{}'".format(self.geo_parcelle) + 'proprietaire': f" AND l10.comptecommunal = '{compte_communal}'", + 'parcelle': f" AND p.parcelle = '{self.geo_parcelle}'" } }, 'proprietes_non_baties': { @@ -218,8 +218,8 @@ def set_composer_templates(self, compte_communal): 'keepContent': True, 'filter': 'comptecommunal', 'and': { - 'proprietaire': " AND p.comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND p.parcelle = '{}'".format(self.geo_parcelle) + 'proprietaire': f" AND p.comptecommunal = '{compte_communal}'", + 'parcelle': f" AND p.parcelle = '{self.geo_parcelle}'" }, 'bgcolor': Qt.transparent }, @@ -242,8 +242,8 @@ def set_composer_templates(self, compte_communal): 'keepContent': True, 'filter': 'comptecommunal', 'and': { - 'proprietaire': " AND comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND comptecommunal = '{}'".format(compte_communal) + 'proprietaire': f" AND comptecommunal = '{compte_communal}'", + 'parcelle': f" AND comptecommunal = '{compte_communal}'" } }, 'proprietes_baties_line': { @@ -253,8 +253,8 @@ def set_composer_templates(self, compte_communal): 'type': 'sql', 'filter': 'comptecommunal', 'and': { - 'proprietaire': " AND l10.comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND p.parcelle = '{}'".format(self.geo_parcelle) + 'proprietaire': f" AND l10.comptecommunal = '{compte_communal}'", + 'parcelle': f" AND p.parcelle = '{self.geo_parcelle}'" } }, 'proprietes_non_baties_line': { @@ -263,8 +263,8 @@ def set_composer_templates(self, compte_communal): 'revenucadastral', 'coll', 'natexo', 'anret', 'fractionrcexo', 'pourcentageexo', 'tc', 'lff'], 'type': 'sql', 'and': { - 'proprietaire': " AND p.comptecommunal = '{}'".format(compte_communal), - 'parcelle': " AND p.parcelle = '{}'".format(self.geo_parcelle) + 'proprietaire': f" AND p.comptecommunal = '{compte_communal}'", + 'parcelle': f" AND p.parcelle = '{self.geo_parcelle}'" } } @@ -314,7 +314,7 @@ def getContentForGivenItem(self, key, item, page=None): # Load SQL query and get data # Get sql file sqlFile = tplPath + '.sql' - fin = open(sqlFile, 'rt', encoding='utf8') + fin = open(sqlFile, encoding='utf8') sql = fin.read() fin.close() @@ -362,7 +362,7 @@ def getContentForGivenItem(self, key, item, page=None): for line in data: replaceDict = {} for i in range(len(item['names'])): - replaceDict['$%s' % item['names'][i]] = u'%s' % line[i] + replaceDict['$%s' % item['names'][i]] = '%s' % line[i] content += self.getHtmlFromTemplate(tplPath, replaceDict) # fill empty data to have full size table @@ -371,7 +371,7 @@ def getContentForGivenItem(self, key, item, page=None): for _ in range(self.maxLineNumber - len(data)): replaceDict = {} for i in range(len(item['names'])): - replaceDict['$%s' % item['names'][i]] = u' ' + replaceDict['$%s' % item['names'][i]] = ' ' content += self.getHtmlFromTemplate(tplPath, replaceDict) elif item['type'] == 'properties': @@ -407,13 +407,13 @@ def replfunc(match): regex = re.compile('|'.join(re.escape(x) for x in replaceDict)) try: - with open(tplPath, 'rt', encoding='utf8') as fin: + with open(tplPath, encoding='utf8') as fin: data = fin.read() data = regex.sub(replfunc, data) return data - except IOError as e: - msg = u"Erreur lors de l'export: %s" % e + except OSError as e: + msg = "Erreur lors de l'export: %s" % e self.go = False # fix_print_with_import print("%s" % msg) @@ -559,10 +559,10 @@ def addParcelleMap(self): vl.commitChanges() vl.updateExtents() props = vl.renderer().symbol().symbolLayer(0).properties() - props['outline_width'] = u'1' - props['outline_color'] = u'0,85,255,255' - props['outline_style'] = u'solid' - props['style'] = u'no' + props['outline_width'] = '1' + props['outline_color'] = '0,85,255,255' + props['outline_style'] = 'solid' + props['style'] = 'no' vl.renderer().setSymbol(QgsFillSymbol.createSimple(props)) self.mProject.addMapLayer(vl) self.redlineLayer = vl @@ -610,7 +610,7 @@ def exportItemAsPdf(self, comptecommunal, suffix=None) -> str: # Create the pdf output path from time import time - temp = "releve_%s_%s_%s.pdf" % ( + temp = "releve_{}_{}_{}.pdf".format( self.etype, comptecommunal.replace('+', 'plus').replace('*', 'fois'), # .replace('¤', 'plus'), int(time() * 100) @@ -622,7 +622,7 @@ def exportItemAsPdf(self, comptecommunal, suffix=None) -> str: # print temp temppath = os.path.join(self.targetDir, temp) temppath = os.path.normpath(temppath) - QgsMessageLog.logMessage('Export PDF vers {}'.format(temppath), 'cadastre', Qgis.Info) + QgsMessageLog.logMessage(f'Export PDF vers {temppath}', 'cadastre', Qgis.Info) # print("export temppath %s" % temppath) # Export as pdf diff --git a/cadastre/cadastre_identify_parcelle.py b/cadastre/cadastre_identify_parcelle.py index d53e6682..9c705f38 100644 --- a/cadastre/cadastre_identify_parcelle.py +++ b/cadastre/cadastre_identify_parcelle.py @@ -20,7 +20,6 @@ * * ***************************************************************************/ """ -from __future__ import absolute_import from qgis.core import ( QgsFeature, diff --git a/cadastre/cadastre_import.py b/cadastre/cadastre_import.py index 268cc851..23128f34 100644 --- a/cadastre/cadastre_import.py +++ b/cadastre/cadastre_import.py @@ -177,14 +177,14 @@ def updateTimer(self): if self.go: b = datetime.now() diff = b - self.startTime - self.qc.updateLog(u'%s s' % diff.seconds) + self.qc.updateLog('%s s' % diff.seconds) def beginImport(self): """ Process to run before importing data """ # Log - jobTitle = u'INITIALISATION' + jobTitle = 'INITIALISATION' self.beginJobLog(2, jobTitle) # Set postgresql synchronous_commit to off @@ -211,7 +211,7 @@ def installCadastreStructure(self): return False # Log - jobTitle = u'STRUCTURATION BDD' + jobTitle = 'STRUCTURATION BDD' self.beginJobLog(6, jobTitle) # Replace dictionnary @@ -225,15 +225,15 @@ def installCadastreStructure(self): # install cadastre structure scriptList = [ { - 'title': u'Création des tables', + 'title': 'Création des tables', 'script': '%s' % os.path.join(self.pScriptDir, 'commun_create_metier.sql') }, { - 'title': u'Création des tables edigeo', + 'title': 'Création des tables edigeo', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_import_tables.sql') }, { - 'title': u'Ajout de la nomenclature', + 'title': 'Ajout de la nomenclature', 'script': '%s' % os.path.join(self.pScriptDir, 'commun_insert_nomenclatures.sql') } ] @@ -283,7 +283,7 @@ def updateCadastreStructure(self): def importMajic(self): # Log - jobTitle = u'MAJIC' + jobTitle = 'MAJIC' self.beginJobLog(13, jobTitle) # dict for parameters replacement @@ -294,7 +294,7 @@ def importMajic(self): scriptList = [] scriptList.append( { - 'title': u'Suppression des contraintes', + 'title': 'Suppression des contraintes', 'script': os.path.join(self.pScriptDir, 'commun_suppression_contraintes.sql'), 'constraints': False, 'divide': True @@ -305,13 +305,13 @@ def importMajic(self): if self.dialog.hasMajicData: scriptList.append( { - 'title': u'Purge des données MAJIC', + 'title': 'Purge des données MAJIC', 'script': os.path.join(self.pScriptDir, 'majic3_purge_donnees.sql') } ) scriptList.append( { - 'title': u'Purge des données brutes', + 'title': 'Purge des données brutes', 'script': os.path.join(self.pScriptDir, 'majic3_purge_donnees_brutes.sql') } ) @@ -319,7 +319,7 @@ def importMajic(self): # Remove indexes scriptList.append( { - 'title': u'Suppression des indexes', + 'title': 'Suppression des indexes', 'script': os.path.join(self.pScriptDir, 'majic3_drop_indexes.sql') } ) @@ -327,7 +327,7 @@ def importMajic(self): # Import MAJIC files into database # No use of COPY FROM to allow import into distant databases importScript = { - 'title': u'Import des fichiers majic', + 'title': 'Import des fichiers majic', 'method': self.import_majic_into_database } scriptList.append(importScript) @@ -335,7 +335,7 @@ def importMajic(self): # Format data scriptList.append( { - 'title': u'Mise en forme des données', + 'title': 'Mise en forme des données', 'script': os.path.join(self.pScriptDir, '%s/majic3_formatage_donnees.sql' % self.dialog.dataVersion), 'divide': True } @@ -345,7 +345,7 @@ def importMajic(self): if self.removeMajicRawData: scriptList.append( { - 'title': u'Purge des données brutes', + 'title': 'Purge des données brutes', 'script': os.path.join(self.pScriptDir, 'majic3_purge_donnees_brutes.sql') } ) @@ -353,17 +353,17 @@ def importMajic(self): # If MAJIC but no EDIGEO afterward # run SQL script to update link between EDI/MAJ if not self.dialog.doEdigeoImport: - replaceDict['[DEPDIR]'] = '%s%s' % (self.dialog.edigeoDepartement, self.dialog.edigeoDirection) + replaceDict['[DEPDIR]'] = f'{self.dialog.edigeoDepartement}{self.dialog.edigeoDirection}' scriptList.append( { - 'title': u'Suppression des indexes', + 'title': 'Suppression des indexes', 'script': os.path.join(self.pScriptDir, 'edigeo_drop_indexes.sql') } ) scriptList.append( { - 'title': u'Mise à jour des liens EDIGEO', + 'title': 'Mise à jour des liens EDIGEO', 'script': os.path.join(self.pScriptDir, 'edigeo_update_majic_link.sql'), 'divide': True } @@ -371,7 +371,7 @@ def importMajic(self): scriptList.append( { - 'title': u'Création des indexes spatiaux', + 'title': 'Création des indexes spatiaux', 'script': os.path.join(self.pScriptDir, 'edigeo_create_indexes.sql'), 'divide': True } @@ -381,7 +381,7 @@ def importMajic(self): replaceDict['2154'] = self.targetSrid scriptList.append( { - 'title': u'Ajout de la table parcelle_info', + 'title': 'Ajout de la table parcelle_info', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_table_parcelle_info_majic.sql'), 'divide': False } @@ -390,7 +390,7 @@ def importMajic(self): # Add constraints scriptList.append( { - 'title': u'Ajout des contraintes', + 'title': 'Ajout des contraintes', 'script': os.path.join(self.pScriptDir, 'commun_creation_contraintes.sql'), 'constraints': True, 'divide': True @@ -514,7 +514,7 @@ def import_majic_into_database(self) -> bool: if len(list(dep_dirs.keys())) > 1: self.go = False lst = ",
".join( - "département : {} et direction : {}".format(a[0:2], a[2:3]) for a in dep_dirs) + f"département : {a[0:2]} et direction : {a[2:3]}" for a in dep_dirs) self.qc.updateLog( "" "ERREUR : MAJIC - Les données concernent des départements et codes direction différents :" @@ -558,7 +558,7 @@ def import_majic_into_database(self) -> bool: return False # 2nd path to insert data - dep_dir = '{}{}'.format(self.dialog.edigeoDepartement, self.dialog.edigeoDirection) + dep_dir = f'{self.dialog.edigeoDepartement}{self.dialog.edigeoDirection}' for item in self.majicSourceFileNames: table = item['table'] self.totalSteps += len(majic_files_found[table]) @@ -604,7 +604,7 @@ def import_majic_into_database(self) -> bool: else: c = self.connector._get_cursor() c.executemany( - 'INSERT INTO {} VALUES (?)'.format(table), + f'INSERT INTO {table} VALUES (?)', [(r.sub(' ', x.strip('\r\n')),) for x in a if x and x[0:3] == dep_dir]) self.connector._commit() c.close() @@ -631,9 +631,9 @@ def importEdigeo(self): return False # Log : Print connection parameters to database - jobTitle = u'EDIGEO' + jobTitle = 'EDIGEO' self.beginJobLog(21, jobTitle) - self.qc.updateLog(u'Type de base : %s, Connexion: %s, Schéma: %s' % ( + self.qc.updateLog('Type de base : {}, Connexion: {}, Schéma: {}'.format( self.dialog.dbType, self.dialog.connectionName, self.dialog.schema @@ -657,7 +657,7 @@ def importEdigeo(self): and self.dialog.dbType == 'postgis': scriptList.append( { - 'title': u'Ajout de la table geo_unite_foncieres', + 'title': 'Ajout de la table geo_unite_foncieres', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_table_unite_fonciere.sql'), 'constraints': False } @@ -666,7 +666,7 @@ def importEdigeo(self): # Drop constraints scriptList.append( { - 'title': u'Suppression des contraintes', + 'title': 'Suppression des contraintes', 'script': '%s' % os.path.join(self.pScriptDir, 'commun_suppression_contraintes.sql'), 'constraints': False, 'divide': True @@ -680,7 +680,7 @@ def importEdigeo(self): self.dropEdigeoRawData() scriptList.append( { - 'title': u'Création des tables edigeo', + 'title': 'Création des tables edigeo', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_import_tables.sql') } ) @@ -688,7 +688,7 @@ def importEdigeo(self): if self.dialog.hasData: scriptList.append( { - 'title': u'Suppression des indexes', + 'title': 'Suppression des indexes', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_drop_indexes.sql') } ) @@ -716,13 +716,13 @@ def importEdigeo(self): # Format edigeo data replaceDict = self.replaceDict.copy() - replaceDict['[DEPDIR]'] = '%s%s' % (self.dialog.edigeoDepartement, self.dialog.edigeoDirection) + replaceDict['[DEPDIR]'] = f'{self.dialog.edigeoDepartement}{self.dialog.edigeoDirection}' scriptList = [] scriptList.append( { - 'title': u'Mise en forme des données', + 'title': 'Mise en forme des données', 'script': os.path.join(self.pScriptDir, 'edigeo_formatage_donnees.sql'), 'divide': True } @@ -730,13 +730,13 @@ def importEdigeo(self): scriptList.append( { - 'title': u'Placement des étiquettes', + 'title': 'Placement des étiquettes', 'script': os.path.join(self.pScriptDir, 'edigeo_add_labels_xy.sql') } ) scriptList.append( { - 'title': u'Création des indexes spatiaux', + 'title': 'Création des indexes spatiaux', 'script': os.path.join(self.pScriptDir, 'edigeo_create_indexes.sql'), 'divide': True } @@ -744,7 +744,7 @@ def importEdigeo(self): scriptList.append( { - 'title': u'Ajout des contraintes', + 'title': 'Ajout des contraintes', 'script': os.path.join(self.pScriptDir, 'commun_creation_contraintes.sql'), 'constraints': True, 'divide': True @@ -757,7 +757,7 @@ def importEdigeo(self): if (self.dialog.doMajicImport or self.dialog.hasMajicDataProp) \ and self.dialog.dbType == 'postgis': scriptList.append( - {'title': u'Création Unités foncières', + {'title': 'Création Unités foncières', 'script': os.path.join(self.pScriptDir, 'edigeo_unites_foncieres_%s.sql' % self.dialog.dbType) } ) @@ -767,7 +767,7 @@ def importEdigeo(self): replaceDict['2154'] = self.targetSrid scriptList.append( { - 'title': u'Ajout de la table parcelle_info', + 'title': 'Ajout de la table parcelle_info', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_table_parcelle_info_majic.sql') } ) @@ -775,7 +775,7 @@ def importEdigeo(self): replaceDict['2154'] = self.targetSrid scriptList.append( { - 'title': u'Ajout de la table parcelle_info', + 'title': 'Ajout de la table parcelle_info', 'script': '%s' % os.path.join(self.pScriptDir, 'edigeo_create_table_parcelle_info_simple.sql') } ) @@ -808,7 +808,7 @@ def endImport(self): Actions done when import has finished """ # Log - jobTitle = u'FINALISATION' + jobTitle = 'FINALISATION' self.beginJobLog(1, jobTitle) # Debug spatialite @@ -826,7 +826,7 @@ def endImport(self): self.executeSqlQuery(sql) # Remove the temp folders - self.dialog.subStepLabel.setText(u'Suppression des données temporaires') + self.dialog.subStepLabel.setText('Suppression des données temporaires') self.updateProgressBar() tempFolderList = [ self.pScriptDir, @@ -838,8 +838,8 @@ def endImport(self): if os.path.exists(rep): shutil.rmtree(rep) # rmt = 1 - except IOError as e: - delmsg = u"Erreur lors de la suppression des répertoires temporaires: %s" % e + except OSError as e: + delmsg = "Erreur lors de la suppression des répertoires temporaires: %s" % e self.qc.updateLog(delmsg) self.go = False @@ -875,9 +875,9 @@ def endImport(self): self.executeSqlQuery(sql) if self.go: - msg = u"Import terminé" + msg = "Import terminé" else: - msg = u"Des erreurs ont été rencontrées pendant l'import. Veuillez consulter le log." + msg = "Des erreurs ont été rencontrées pendant l'import. Veuillez consulter le log." self.updateProgressBar() self.updateTimer() @@ -900,7 +900,7 @@ def copyFilesToTemp(self, source, target): """ if self.go: - self.qc.updateLog(u'* Copie du répertoire %s' % source) + self.qc.updateLog('* Copie du répertoire %s' % source) QApplication.setOverrideCursor(Qt.WaitCursor) @@ -908,8 +908,8 @@ def copyFilesToTemp(self, source, target): try: dir_util.copy_tree(source, target) os.chmod(target, 0o777) - except IOError as e: - msg = u"Erreur lors de la copie des scripts d'import: %s" % e + except OSError as e: + msg = "Erreur lors de la copie des scripts d'import: %s" % e QMessageBox.information(self.dialog, "Cadastre", msg) self.go = False @@ -966,7 +966,7 @@ def unzipFolderContent(self, path): """ if self.go: QApplication.setOverrideCursor(Qt.WaitCursor) - self.qc.updateLog(u'* Décompression des fichiers') + self.qc.updateLog('* Décompression des fichiers') # get all the zip files zipFileList = self.list_files_in_directory(path, ['zip']) @@ -1005,7 +1005,7 @@ def unzipFolderContent(self, path): # untar all tar.bz2 in source folder self.qc.updateLog('* Recherche des fichiers .bz2') tarFileListA = self.list_files_in_directory(path, ['bz2']) - self.qc.updateLog("{} fichier(s) .bz2 dans {}".format(len(tarFileListA), path)) + self.qc.updateLog(f"{len(tarFileListA)} fichier(s) .bz2 dans {path}") for z in tarFileListA: with tarfile.open(z) as t: try: @@ -1022,7 +1022,7 @@ def unzipFolderContent(self, path): # untar all new tar.bz2 found in self.edigeoPlainDir tarFileListB = self.list_files_in_directory(self.edigeoPlainDir, ['bz2']) - self.qc.updateLog("{} fichier(s) .bz2 dans {}".format(len(tarFileListA), self.edigeoPlainDir)) + self.qc.updateLog(f"{len(tarFileListA)} fichier(s) .bz2 dans {self.edigeoPlainDir}") for z in tarFileListB: with tarfile.open(z) as t: try: @@ -1042,7 +1042,7 @@ def unzipFolderContent(self, path): self.qc.updateLog("Erreur lors de la suppression de %s" % str(z)) pass # in Windows, sometime file is not unlocked - except IOError: + except OSError: msg = "Erreur lors de l'extraction des fichiers EDIGEO" self.go = False self.qc.updateLog(msg) @@ -1086,8 +1086,8 @@ def replaceParametersInScript(self, scriptPath, replaceDict): with open(scriptPath, 'w', encoding='utf8') as fout: fout.write(data) - except IOError as e: - msg = u"Erreur lors du paramétrage des scripts d'import: %s" % e + except OSError as e: + msg = "Erreur lors du paramétrage des scripts d'import: %s" % e self.go = False self.qc.updateLog(msg) return msg @@ -1271,13 +1271,13 @@ def regexp(motif, item): except BaseError as e: if not re.search(r'CREATE INDEX ', sql, re.IGNORECASE): self.go = False - self.qc.updateLog(u"Erreur rencontrée pour la requête:

%s

" % sql) - self.qc.updateLog(u"Erreur

%s

" % e.msg) + self.qc.updateLog("Erreur rencontrée pour la requête:

%s

" % sql) + self.qc.updateLog("Erreur

%s

" % e.msg) except sqlite.OperationalError as e: if not re.search(r'CREATE INDEX ', sql, re.IGNORECASE): self.go = False - self.qc.updateLog(u"Erreur rencontrée pour la requête:

%s

" % sql) - self.qc.updateLog(u"Erreur

%s

" % format(e)) + self.qc.updateLog("Erreur rencontrée pour la requête:

%s

" % sql) + self.qc.updateLog("Erreur

%s

" % format(e)) finally: QApplication.restoreOverrideCursor() if c: @@ -1298,14 +1298,14 @@ def importAllEdigeoToDatabase(self): if self.go: - self.qc.updateLog(u'* Import des fichiers EDIGEO dans la base') + self.qc.updateLog('* Import des fichiers EDIGEO dans la base') initialStep = self.step initialTotalSteps = self.totalSteps # THF - self.dialog.subStepLabel.setText(u'Import des fichiers via ogr2ogr (*.thf)') - self.qc.updateLog(u' - Import des fichiers via ogr2ogr') + self.dialog.subStepLabel.setText('Import des fichiers via ogr2ogr (*.thf)') + self.qc.updateLog(' - Import des fichiers via ogr2ogr') # Get plain files in source directory thfList1 = self.list_files_in_directory(self.dialog.edigeoSourceDir, ['thf']) # Get files which have been uncompressed by plugin in temp folder @@ -1322,8 +1322,8 @@ def importAllEdigeoToDatabase(self): if self.go: # VEC - import relations between objects - self.dialog.subStepLabel.setText(u'Import des relations (*.vec)') - self.qc.updateLog(u' - Import des relations (*.vec)') + self.dialog.subStepLabel.setText('Import des relations (*.vec)') + self.qc.updateLog(' - Import des relations (*.vec)') # Get plain files in source directory vecList1 = self.list_files_in_directory(self.dialog.edigeoSourceDir, ['vec']) # Get files which have been uncompressed by plugin in temp folder @@ -1341,7 +1341,7 @@ def importAllEdigeoToDatabase(self): break if self.go: self.qc.updateLog( - u' - %s multipolygones mis à jours dans la base de données' % self.multiPolygonUpdated) + ' - %s multipolygones mis à jours dans la base de données' % self.multiPolygonUpdated) # Reinit progress var self.step = initialStep @@ -1362,7 +1362,7 @@ def importEdigeoThfToDatabase(self, filename): # Build ogr2ogr command conn_name = self.dialog.connectionName settings = QSettings() - settings.beginGroup(u"/%s/%s" % (self.db.dbplugin().connectionSettingsKey(), conn_name)) + settings.beginGroup(f"/{self.db.dbplugin().connectionSettingsKey()}/{conn_name}") # normalising file path filename = os.path.normpath(filename) @@ -1370,10 +1370,10 @@ def importEdigeoThfToDatabase(self, filename): if not settings.contains("database"): # non-existent entry? raise Exception(self.tr('There is no defined database connection "%s".') % conn_name) settingsList = ["service", "host", "port", "database", "username", "password"] - service, host, port, database, username, password = [settings.value(x) for x in settingsList] + service, host, port, database, username, password = (settings.value(x) for x in settingsList) if service: - pg_access = 'PG:service=%s active_schema=%s' % ( + pg_access = 'PG:service={} active_schema={}'.format( service, self.dialog.schema ) @@ -1382,7 +1382,7 @@ def importEdigeoThfToDatabase(self, filename): if not host: host = "localhost" - pg_access = 'PG:host=%s port=%s dbname=%s active_schema=%s user=%s password=%s' % ( + pg_access = 'PG:host={} port={} dbname={} active_schema={} user={} password={}'.format( host, port, database, @@ -1409,7 +1409,7 @@ def importEdigeoThfToDatabase(self, filename): if self.dialog.dbType == 'spatialite': if not settings.contains("sqlitepath"): # non-existent entry? self.go = False - raise Exception(u'there is no defined database connection "%s".' % conn_name) + raise Exception('there is no defined database connection "%s".' % conn_name) database = settings.value("sqlitepath") @@ -1446,7 +1446,7 @@ def importEdigeoThfToDatabase(self, filename): if not self.go: self.qc.updateLog( - u"Erreur - L'import des données via OGR2OGR a échoué:\n\n%s\n\n%s" % ( + "Erreur - L'import des données via OGR2OGR a échoué:\n\n{}\n\n{}".format( printedString, cmdArgs ) @@ -1476,7 +1476,7 @@ def importEdigeoVecToDatabase(self, path): if self.dialog.dbType == 'postgis': sql = "BEGIN;" for item in l: - sql += "INSERT INTO edigeo_rel ( nom, de, vers) VALUES ( '%s', '%s', '%s');" % ( + sql += "INSERT INTO edigeo_rel ( nom, de, vers) VALUES ( '{}', '{}', '{}');".format( item[0], item[1], item[2]) sql += "COMMIT;" sql = CadastreCommon.setSearchPath(sql, self.dialog.schema) @@ -1557,7 +1557,7 @@ def getUpdateMultipolygonFromVecQuery(self, path, layerType='edigeo'): sql = '' for obj, wkt in list(item.items()): self.multiPolygonUpdated += 1 - sql += " UPDATE %s SET geom = ST_Transform(ST_GeomFromText('%s', %s), %s)" % ( + sql += " UPDATE {} SET geom = ST_Transform(ST_GeomFromText('{}', {}), {})".format( table, wkt, self.sourceSrid, @@ -1569,10 +1569,10 @@ def getUpdateMultipolygonFromVecQuery(self, path, layerType='edigeo'): # ~ sql+= " AND geom != ST_Transform(ST_GeomFromText('%s', %s), %s) " % (wkt, self.sourceSrid, self.targetSrid) # only if the 2 geometries are related (object_rid is not unique) if self.dialog.dbType == 'postgis': - sql += " AND geom @ ST_Transform(ST_GeomFromText('%s', %s), %s) ; " % ( + sql += " AND geom @ ST_Transform(ST_GeomFromText('{}', {}), {}) ; ".format( wkt, self.sourceSrid, self.targetSrid) else: - sql += " AND ST_Intersects(geom, ST_Transform(ST_GeomFromText('%s', %s), %s) ); " % ( + sql += " AND ST_Intersects(geom, ST_Transform(ST_GeomFromText('{}', {}), {}) ); ".format( wkt, self.sourceSrid, self.targetSrid) sqlList.append(sql) diff --git a/cadastre/cadastre_loading.py b/cadastre/cadastre_loading.py index f58cd370..9c09b635 100644 --- a/cadastre/cadastre_loading.py +++ b/cadastre/cadastre_loading.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ /*************************************************************************** Cadastre - loading main methods @@ -346,7 +345,7 @@ def __init__(self, dialog): def updateTimer(self): b = datetime.now() diff = b - self.startTime - self.qc.updateLog(u'%s s' % diff.seconds) + self.qc.updateLog('%s s' % diff.seconds) def getGroupIndex(self, groupName): """ @@ -404,7 +403,7 @@ def processLoading(self): if cadastreSvgPath not in a: a.append(cadastreSvgPath) s.setValue("svg/searchPathsForSVG", a) - self.qc.updateLog(u"* Le chemin contenant les SVG du plugin Cadastre a été ajouté dans les options de QGIS") + self.qc.updateLog("* Le chemin contenant les SVG du plugin Cadastre a été ajouté dans les options de QGIS") # Get selected options providerName = self.dialog.dbpluginclass.providerName() @@ -414,7 +413,7 @@ def processLoading(self): # Run the loading self.updateTimer() - self.qc.updateLog(u'Chargement des tables :') + self.qc.updateLog('Chargement des tables :') # Get database list of tables if self.dialog.dbType == 'postgis': @@ -429,7 +428,7 @@ def processLoading(self): communeFilter = None cExp = QgsExpression(communeExpression) if communeExpression != '' and not cExp.hasParserError(): - self.qc.updateLog(u'Filtrage à partir des communes : %s' % communeExpression) + self.qc.updateLog('Filtrage à partir des communes : %s' % communeExpression) cReq = QgsFeatureRequest(cExp) cTableList = [a for a in dbTables if a.name == 'geo_commune'] cTable = cTableList[0] @@ -450,7 +449,7 @@ def processLoading(self): if len(cids): communeFilter = cids else: - self.qc.updateLog(u'Filtrage à partir des communes, expression invalide : %s' % cExp.parserErrorString()) + self.qc.updateLog('Filtrage à partir des communes, expression invalide : %s' % cExp.parserErrorString()) # Loop through qgisCadastreLayerList and load each corresponding table for item in self.qgisCadastreLayerList: @@ -462,14 +461,14 @@ def processLoading(self): continue # update progress bar - self.qc.updateLog(u'* %s' % item['label']) + self.qc.updateLog('* %s' % item['label']) self.dialog.step += 1 self.qc.updateProgressBar() # Tables - Get db_manager table instance tableList = [a for a in dbTables if a.name == item['table']] if len(tableList) == 0 and 'isView' not in item: - self.qc.updateLog(u' - Aucune table trouvée pour %s' % item['label']) + self.qc.updateLog(' - Aucune table trouvée pour %s' % item['label']) continue if tableList: @@ -542,7 +541,7 @@ def processLoading(self): # apply style qmlPath = os.path.join( self.qc.plugin_dir, - "styles/%s/%s.qml" % (self.themeDir, item['name']) + "styles/{}/{}.qml".format(self.themeDir, item['name']) ) if os.path.exists(qmlPath): vlayer.loadNamedStyle(qmlPath) @@ -558,7 +557,7 @@ def processLoading(self): canvas.freeze(True) # Add all layers to QGIS registry (but not yet to the layer tree) - self.qc.updateLog(u'Ajout des couches dans le registre de QGIS') + self.qc.updateLog('Ajout des couches dans le registre de QGIS') QgsProject.instance().addMapLayers(qgisCadastreLayers, False) self.updateTimer() @@ -645,7 +644,7 @@ def processLoading(self): self.updateTimer() # Zoom to full extent - self.qc.updateLog(u'Zoom sur les couches') + self.qc.updateLog('Zoom sur les couches') canvas.zoomToFullExtent() canvas.freeze(False) canvas.refresh() @@ -656,7 +655,7 @@ def processLoading(self): self.qc.updateProgressBar() # Emit signal - self.qc.updateLog(u'Mise à jour des outils cadastre') + self.qc.updateLog('Mise à jour des outils cadastre') self.cadastreLoadingFinished.emit() self.updateTimer() @@ -664,8 +663,8 @@ def processLoading(self): QApplication.restoreOverrideCursor() QMessageBox.information( self.dialog, - u"Cadastre", - u"Les données ont bien été chargées dans QGIS" + "Cadastre", + "Les données ont bien été chargées dans QGIS" ) self.dialog.pbProcess.setValue(0) @@ -704,4 +703,4 @@ def loadSqlLayer(self): QgsProject.instance().addMapLayers([layer], True) else: self.qc.updateLog( - u"La couche n'est pas valide et n'a pu être chargée. Pour PostGIS, avez-vous pensé à indiquer le schéma comme préfixe des tables ?") + "La couche n'est pas valide et n'a pu être chargée. Pour PostGIS, avez-vous pensé à indiquer le schéma comme préfixe des tables ?") diff --git a/cadastre/cadastre_menu.py b/cadastre/cadastre_menu.py index e60ab682..42849b5a 100644 --- a/cadastre/cadastre_menu.py +++ b/cadastre/cadastre_menu.py @@ -24,7 +24,6 @@ from time import time from qgis.core import ( - Qgis, QgsApplication, QgsLayoutExporter, QgsPrintLayout, @@ -303,7 +302,7 @@ def export_view(self): QApplication.setOverrideCursor(Qt.WaitCursor) template_content = None - with open(f, 'rt', encoding='utf8') as ff: + with open(f, encoding='utf8') as ff: template_content = ff.read() if not template_content: return @@ -500,7 +499,7 @@ def open_message_dialog(self): if version in versionMessages: message += '
    ' for item in versionMessages[version]: - message += '
  • %s - %s
  • ' % (item[0], item[1]) + message += f'
  • {item[0]} - {item[1]}
  • ' message += '
' message += '

Changelog

' @@ -547,7 +546,7 @@ def run_tests(pattern='test_*.py', package=None): try: from cadastre.tests.runner import test_package if package is None: - package = '{}.__init__'.format(Path(__file__).parent.name) + package = f'{Path(__file__).parent.name}.__init__' test_package(package, pattern) except (AttributeError, ModuleNotFoundError): message = 'Could not load tests. Are you using a production package?' diff --git a/cadastre/dialogs/about_dialog.py b/cadastre/dialogs/about_dialog.py index 6cc6aa2a..aa3a9571 100644 --- a/cadastre/dialogs/about_dialog.py +++ b/cadastre/dialogs/about_dialog.py @@ -26,11 +26,11 @@ class CadastreAboutDialog(QDialog, ABOUT_FORM_CLASS): """ About - Let the user display the about dialog. """ def __init__(self, iface, parent=None): - super(CadastreAboutDialog, self).__init__(parent) + super().__init__(parent) self.iface = iface self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') # Signals/Slot Connections self.rejected.connect(self.onReject) diff --git a/cadastre/dialogs/cadastre_export_dialog.py b/cadastre/dialogs/cadastre_export_dialog.py index 5609a728..b29715b1 100644 --- a/cadastre/dialogs/cadastre_export_dialog.py +++ b/cadastre/dialogs/cadastre_export_dialog.py @@ -41,10 +41,10 @@ class cadastrePrintProgress(QDialog, PRINT_FORM_CLASS): def __init__(self, parent=None): - super(cadastrePrintProgress, self).__init__(parent) + super().__init__(parent) # Set up the user interface self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') from contextlib import contextmanager diff --git a/cadastre/dialogs/cadastre_load_dialog.py b/cadastre/dialogs/cadastre_load_dialog.py index 0c4ec5c8..1c30167b 100644 --- a/cadastre/dialogs/cadastre_load_dialog.py +++ b/cadastre/dialogs/cadastre_load_dialog.py @@ -26,10 +26,10 @@ class CadastreLoadDialog(QDialog, LOAD_FORM_CLASS): """ Load data from database. """ def __init__(self, iface, cadastre_search_dialog, parent=None): - super(CadastreLoadDialog, self).__init__(parent) + super().__init__(parent) self.iface = iface self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') self.mc = self.iface.mapCanvas() self.cadastre_search_dialog = cadastre_search_dialog diff --git a/cadastre/dialogs/custom_qcompleter.py b/cadastre/dialogs/custom_qcompleter.py index e78ffee7..9c831246 100644 --- a/cadastre/dialogs/custom_qcompleter.py +++ b/cadastre/dialogs/custom_qcompleter.py @@ -18,7 +18,7 @@ class CustomQCompleter(QCompleter): """ def __init__(self, *args): # parent=None): - super(CustomQCompleter, self).__init__(*args) + super().__init__(*args) self.local_completion_prefix = "" self.source_model = None self.filterProxyModel = QSortFilterProxyModel(self) @@ -28,7 +28,7 @@ def setModel(self, model): self.source_model = model self.filterProxyModel = QSortFilterProxyModel(self) self.filterProxyModel.setSourceModel(self.source_model) - super(CustomQCompleter, self).setModel(self.filterProxyModel) + super().setModel(self.filterProxyModel) self.usingOriginalModel = True def updateModel(self): diff --git a/cadastre/dialogs/custom_qpush_button.py b/cadastre/dialogs/custom_qpush_button.py index 31801b14..95125c43 100644 --- a/cadastre/dialogs/custom_qpush_button.py +++ b/cadastre/dialogs/custom_qpush_button.py @@ -10,7 +10,7 @@ class CustomPushButton(QPushButton): def __init__(self, *args): - super(CustomPushButton, self).__init__(*args) + super().__init__(*args) def initPushButton( self, sizeWidth, sizeHeight, coordX, coordY, name, text, diff --git a/cadastre/dialogs/dialog_common.py b/cadastre/dialogs/dialog_common.py index c9dfbfa0..fa637b6b 100644 --- a/cadastre/dialogs/dialog_common.py +++ b/cadastre/dialogs/dialog_common.py @@ -51,7 +51,7 @@ def updateLog(self, msg): t.ensureCursorVisible() prefix = '' suffix = '' - t.append('%s %s %s' % (prefix, msg, suffix)) + t.append(f'{prefix} {msg} {suffix}') c = t.textCursor() c.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) t.setTextCursor(c) @@ -178,7 +178,7 @@ def updateSchemaList(self): return except: self.dialog.go = False - msg = u"Impossible de récupérer les schémas de la base. Vérifier les informations de connexion." + msg = "Impossible de récupérer les schémas de la base. Vérifier les informations de connexion." self.updateLog(msg) QApplication.restoreOverrideCursor() return @@ -235,7 +235,7 @@ def checkDatabaseForExistingStructure(self): # Check for data in it sql = 'SELECT * FROM "%s" LIMIT 1' % searchTable if self.dialog.dbType == 'postgis': - sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.dialog.schema, searchTable) + sql = f'SELECT * FROM "{self.dialog.schema}"."{searchTable}" LIMIT 1' data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(self.dialog.db.connector, sql) if ok and rowCount >= 1: hasData = True @@ -243,7 +243,7 @@ def checkDatabaseForExistingStructure(self): # Check for Majic data in it sql = 'SELECT * FROM "%s" LIMIT 1' % majicTableParcelle if self.dialog.dbType == 'postgis': - sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.dialog.schema, majicTableParcelle) + sql = f'SELECT * FROM "{self.dialog.schema}"."{majicTableParcelle}" LIMIT 1' data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(self.dialog.db.connector, sql) if ok and rowCount >= 1: hasMajicData = True @@ -252,7 +252,7 @@ def checkDatabaseForExistingStructure(self): # Check for Majic data in it sql = 'SELECT * FROM "%s" LIMIT 1' % majicTableProp if self.dialog.dbType == 'postgis': - sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.dialog.schema, majicTableProp) + sql = f'SELECT * FROM "{self.dialog.schema}"."{majicTableProp}" LIMIT 1' data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(self.dialog.db.connector, sql) if ok and rowCount >= 1: hasMajicData = True @@ -261,7 +261,7 @@ def checkDatabaseForExistingStructure(self): # Check for Majic data in it sql = 'SELECT * FROM "%s" LIMIT 1' % majicTableVoie if self.dialog.dbType == 'postgis': - sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.dialog.schema, majicTableVoie) + sql = f'SELECT * FROM "{self.dialog.schema}"."{majicTableVoie}" LIMIT 1' data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(self.dialog.db.connector, sql) if ok and rowCount >= 1: hasMajicData = True @@ -286,7 +286,7 @@ def checkDatabaseForExistingTable(self, tableName, schemaName=''): return False if self.dialog.dbType == 'postgis': - sql = "SELECT * FROM information_schema.tables WHERE table_schema = '%s' AND table_name = '%s'" % ( + sql = "SELECT * FROM information_schema.tables WHERE table_schema = '{}' AND table_name = '{}'".format( schemaName, tableName) if self.dialog.dbType == 'spatialite': @@ -339,12 +339,12 @@ def createNewSpatialiteDatabase(self): # Let the user choose new file path ipath, __ = QFileDialog.getSaveFileName( None, - u"Choisir l'emplacement du nouveau fichier", + "Choisir l'emplacement du nouveau fichier", str(os.path.expanduser("~").encode('utf-8')).strip(' \t'), "Sqlite database (*.sqlite)" ) if not ipath: - self.updateLog(u"Aucune base de données créée (annulation)") + self.updateLog("Aucune base de données créée (annulation)") return None # Delete file if exists (question already asked above) @@ -362,7 +362,7 @@ def createNewSpatialiteDatabase(self): con.close() del con except: - self.updateLog(u"Échec lors de la création du fichier Spatialite !") + self.updateLog("Échec lors de la création du fichier Spatialite !") return None # Create QGIS connexion diff --git a/cadastre/dialogs/import_dialog.py b/cadastre/dialogs/import_dialog.py index 67c1c422..05a90f75 100644 --- a/cadastre/dialogs/import_dialog.py +++ b/cadastre/dialogs/import_dialog.py @@ -31,9 +31,9 @@ class CadastreImportDialog(QDialog, IMPORT_FORM_CLASS): def __init__(self, iface, parent=None): self.iface = iface - super(CadastreImportDialog, self).__init__(parent) + super().__init__(parent) self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') # Images plugin_dir = str(Path(__file__).resolve().parent.parent) @@ -182,7 +182,7 @@ def chooseDataPath(self, key): """ ipath = QFileDialog.getExistingDirectory( None, - u"Choisir le répertoire contenant les fichiers", + "Choisir le répertoire contenant les fichiers", str(self.pathSelectors[key]['input'].text().encode('utf-8')).strip(' \t') ) if os.path.exists(str(ipath)): @@ -267,27 +267,27 @@ def checkImportInputData(self): msg = '' if not self.db: - msg += u'Veuillez sélectionner une base de données\n' + msg += 'Veuillez sélectionner une base de données\n' if not self.doMajicImport and not self.doEdigeoImport: - msg += u'Veuillez sélectionner le chemin vers les fichiers à importer !\n' + msg += 'Veuillez sélectionner le chemin vers les fichiers à importer !\n' if self.edigeoSourceDir and not self.doEdigeoImport: - msg += u"Le chemin spécifié pour les fichiers EDIGEO n'existe pas\n" + msg += "Le chemin spécifié pour les fichiers EDIGEO n'existe pas\n" if self.majicSourceDir and not self.doMajicImport: - msg += u"Le chemin spécifié pour les fichiers MAJIC n'existe pas\n" + msg += "Le chemin spécifié pour les fichiers MAJIC n'existe pas\n" if self.doEdigeoImport and not self.edigeoSourceProj: - msg += u'La projection source doit être renseignée !\n' + msg += 'La projection source doit être renseignée !\n' if self.doEdigeoImport and not self.edigeoTargetProj: - msg += u'La projection cible doit être renseignée !\n' + msg += 'La projection cible doit être renseignée !\n' if len(self.edigeoDepartement) != 2: - msg += u'Le département ne doit pas être vide !\n' + msg += 'Le département ne doit pas être vide !\n' if not self.edigeoDirection: - msg += u'La direction doit être un entier (0 par défaut) !\n' + msg += 'La direction doit être un entier (0 par défaut) !\n' if not self.edigeoLot: - msg += u'Merci de renseigner un lot pour cet import (code commune, date d\'import, etc.)\n' + msg += 'Merci de renseigner un lot pour cet import (code commune, date d\'import, etc.)\n' self.qc.updateLog(msg.replace('\n', '
')) return msg @@ -299,7 +299,7 @@ def processImport(self): msg = self.checkImportInputData() if msg: - QMessageBox.critical(self, u"Cadastre", msg) + QMessageBox.critical(self, "Cadastre", msg) return # Store settings diff --git a/cadastre/dialogs/message_dialog.py b/cadastre/dialogs/message_dialog.py index 813843e6..484d386a 100644 --- a/cadastre/dialogs/message_dialog.py +++ b/cadastre/dialogs/message_dialog.py @@ -25,10 +25,10 @@ class CadastreMessageDialog(QDialog, MESSAGE_FORM_CLASS): """ Displays a message to the user. """ def __init__(self, iface, message, parent=None): - super(CadastreMessageDialog, self).__init__(parent) + super().__init__(parent) self.iface = iface self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') self.teMessage.setText(message) diff --git a/cadastre/dialogs/options_dialog.py b/cadastre/dialogs/options_dialog.py index 6cfc570e..07ce9cf0 100644 --- a/cadastre/dialogs/options_dialog.py +++ b/cadastre/dialogs/options_dialog.py @@ -28,10 +28,10 @@ class CadastreOptionDialog(QDialog, OPTION_FORM_CLASS): """ Let the user configure options. """ def __init__(self, iface, parent=None): - super(CadastreOptionDialog, self).__init__(parent) + super().__init__(parent) self.iface = iface self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') # Images self.plugin_dir = str(Path(__file__).resolve().parent.parent) @@ -89,15 +89,15 @@ def chooseDataPath(self, key): if self.pathSelectors[key]['type'] == 'dir': ipath = QFileDialog.getExistingDirectory( None, - u"Choisir le répertoire contenant les fichiers", + "Choisir le répertoire contenant les fichiers", str(self.pathSelectors[key]['input'].text().encode('utf-8')).strip(' \t') ) else: ipath, __ = QFileDialog.getOpenFileName( None, - u"Choisir le modèle de composeur utilisé pour l'export", + "Choisir le modèle de composeur utilisé pour l'export", str(self.pathSelectors[key]['input'].text().encode('utf-8')).strip(' \t'), - u"Composeur (*.qpt)" + "Composeur (*.qpt)" ) if os.path.exists(str(ipath)): @@ -160,19 +160,19 @@ def applyInterface(self, key): self.plugin_dir, 'interface/' ) - interfaceInfo = u''' - Pour appliquer l'interface %s + interfaceInfo = ''' + Pour appliquer l'interface {}
  • Menu Préférences > Personnalisation
  • Bouton Charger depuis le fichier (icône dossier ouvert)
  • -
  • Sélectionner le fichier %s.ini situé dans le dossier : %s
  • +
  • Sélectionner le fichier {}.ini situé dans le dossier : {}
  • Appliquer et fermer la fenêtre
  • Redémarer QGIS
- ''' % (key, key.lower(), iniPath) + '''.format(key, key.lower(), iniPath) QMessageBox.information( self, - u"Cadastre - Personnalisation", + "Cadastre - Personnalisation", interfaceInfo ) diff --git a/cadastre/dialogs/parcelle_dialog.py b/cadastre/dialogs/parcelle_dialog.py index fb1f3f7e..bab801f0 100644 --- a/cadastre/dialogs/parcelle_dialog.py +++ b/cadastre/dialogs/parcelle_dialog.py @@ -40,7 +40,7 @@ class CadastreParcelleDialog(QDialog, PARCELLE_FORM_CLASS): """ Show parcelle information. """ def __init__(self, iface, layer, feature, cadastre_search_dialog, parent=None): - super(CadastreParcelleDialog, self).__init__(parent) + super().__init__(parent) plugin_dir = str(Path(__file__).resolve().parent.parent) @@ -49,7 +49,7 @@ def __init__(self, iface, layer, feature, cadastre_search_dialog, parent=None): self.layer = layer self.mc = iface.mapCanvas() self.setupUi(self) - self.setWindowTitle('{} {}'.format(self.windowTitle(), set_window_title())) + self.setWindowTitle(f'{self.windowTitle()} {set_window_title()}') self.cadastre_search_dialog = cadastre_search_dialog self.setWindowIcon(QIcon( os.path.join( @@ -97,7 +97,7 @@ def __init__(self, iface, layer, feature, cadastre_search_dialog, parent=None): connector = CadastreCommon.getConnectorFromUri(connectionParams) self.connector = connector - self.buttonBox.button(QDialogButtonBox.Ok).setText(u"Fermer") + self.buttonBox.button(QDialogButtonBox.Ok).setText("Fermer") # Signals/Slot Connections self.rejected.connect(self.onReject) @@ -180,7 +180,7 @@ def printInfosTab(self): document = QTextDocument() title = self.windowTitle().replace("Cadastre+, ID", "").title() document.setHtml( - "

%s

%s
" % ( + "

{}

{}
".format( title, obj.toHtml() ) ) @@ -219,7 +219,7 @@ def copyInfosTab(self): title = self.windowTitle().replace("Cadastre+, ID", "").title() QApplication.clipboard().setText( - "

%s

%s
" % ( + "

{}

{}
".format( title, obj.toHtml() ) ) @@ -243,11 +243,11 @@ def saveInfosTab(self): title = self.windowTitle().replace("Cadastre+, ID", "").title() with open(fileName, 'w', encoding="ansi", errors="surrogateescape") as inFile: inFile.write( - "

%s

%s
" % ( + "

{}

{}
".format( title, obj.toHtml() ) ) - self.txtLog.setText(u'fichier sauvegarde sous : %s !' % fileName) + self.txtLog.setText('fichier sauvegarde sous : %s !' % fileName) def contextMnubutActions(self, obj): actions = { @@ -325,7 +325,7 @@ def getCss(self): Get CSS from CSS file """ plugin_dir = str(Path(__file__).resolve().parent.parent) - with open(os.path.join(plugin_dir, 'scripts', 'css', 'cadastre.css'), 'r', encoding='utf8') as f: + with open(os.path.join(plugin_dir, 'scripts', 'css', 'cadastre.css'), encoding='utf8') as f: css = f.read() self.css = css @@ -414,7 +414,7 @@ def export_as_pdf(self, key): return if not self.hasMajicDataProp: - self.proprietairesInfo.setText(u'Pas de données de propriétaires dans la base') + self.proprietairesInfo.setText('Pas de données de propriétaires dans la base') return # Check if PDF must be exported for a third party or not @@ -501,7 +501,7 @@ def selectParcellesProprietaire(self): Needs refactoring """ if not self.hasMajicDataProp: - self.proprietairesInfo.setText(u'Pas de données de propriétaires dans la base') + self.proprietairesInfo.setText('Pas de données de propriétaires dans la base') return qs = self.cadastre_search_dialog diff --git a/cadastre/dialogs/search_dialog.py b/cadastre/dialogs/search_dialog.py index d3619b3a..e2f90d49 100644 --- a/cadastre/dialogs/search_dialog.py +++ b/cadastre/dialogs/search_dialog.py @@ -47,7 +47,7 @@ class CadastreSearchDialog(QDockWidget, SEARCH_FORM_CLASS): def __init__(self, iface, parent=None): # QDockWidget.__init__(self) - super(CadastreSearchDialog, self).__init__(parent) + super().__init__(parent) self.iface = iface self.setupUi(self) self.iface.addDockWidget(Qt.RightDockWidgetArea, self) @@ -378,7 +378,7 @@ def checkMajicContent(self): is_postgis = (self.connectionParams['dbType'] == 'postgis') # Get data from table proprietaire - sql = 'SELECT * FROM "{}" LIMIT 1'.format(majicTableProp) + sql = f'SELECT * FROM "{majicTableProp}" LIMIT 1' if is_postgis: sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.connectionParams['schema'], majicTableProp) data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(connector, sql) @@ -386,7 +386,7 @@ def checkMajicContent(self): self.hasMajicDataProp = True # Get data from table voie - sql = 'SELECT * FROM "{}" LIMIT 1'.format(majicTableVoie) + sql = f'SELECT * FROM "{majicTableVoie}" LIMIT 1' if is_postgis: sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.connectionParams['schema'], majicTableVoie) data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(connector, sql) @@ -394,7 +394,7 @@ def checkMajicContent(self): self.hasMajicDataVoie = True # Get data from table parcelle - sql = 'SELECT * FROM "{}" LIMIT 1'.format(majicTableParcelle) + sql = f'SELECT * FROM "{majicTableParcelle}" LIMIT 1' if is_postgis: sql = 'SELECT * FROM "{}"."{}" LIMIT 1'.format(self.connectionParams['schema'], majicTableParcelle) data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(connector, sql) @@ -409,10 +409,10 @@ def checkMajicContent(self): if not self.hasMajicDataParcelle or not self.hasMajicDataVoie: self.qc.updateLog( - u"Pas de données MAJIC non bâties et/ou fantoir -> désactivation de la recherche d'adresse") + "Pas de données MAJIC non bâties et/ou fantoir -> désactivation de la recherche d'adresse") if not self.hasMajicDataProp: self.qc.updateLog( - u"Pas de données MAJIC propriétaires -> désactivation de la recherche de propriétaires") + "Pas de données MAJIC propriétaires -> désactivation de la recherche de propriétaires") def setupSearchCombobox(self, combo, filterExpression=None, queryMode='qgis'): """ @@ -469,7 +469,7 @@ def setupSearchCombobox(self, combo, filterExpression=None, queryMode='qgis'): if filterExpression and queryMode == 'qgis': qe = QgsExpression(filterExpression) if queryMode == 'sql': - emptyLabel = u'%s item(s)' % len(features) + emptyLabel = '%s item(s)' % len(features) else: emptyLabel = '' cb.addItem('%s' % emptyLabel, '') @@ -568,7 +568,7 @@ def refreshAutocomplete(self, key): if len(sp) > 0 and self.qc.normalizeString(sp[0]) in stopwords: searchValue = ' '.join(sp[1:]) if len(self.qc.normalizeString(searchValue)) < minlen: - self.qc.updateLog(u"%s caractères minimum requis pour la recherche !" % minlen) + self.qc.updateLog("%s caractères minimum requis pour la recherche !" % minlen) QApplication.restoreOverrideCursor() return None @@ -677,7 +677,7 @@ def refreshAutocomplete(self, key): data, rowCount, ok = CadastreCommon.fetchDataFromSqlQuery(connector, sql) # Write message in log - msg = u"%s résultats correpondent à '%s'" % (rowCount, searchValue) + msg = f"{rowCount} résultats correpondent à '{searchValue}'" if key == 'adresse' and hasCommuneFilter: msg += ' pour la commune %s' % searchCom # self.qc.updateLog(msg) @@ -691,7 +691,7 @@ def refreshAutocomplete(self, key): maxStringSize = 0 for line in data: if key == 'adresse': - label = '%s | %s %s' % ( + label = '{} | {} {}'.format( line[1].strip(), line[2].strip(), line[3].strip() @@ -700,7 +700,7 @@ def refreshAutocomplete(self, key): if key == 'proprietaire': # ~ label = '%s - %s | %s' % (line[3], line[2], line[0].strip()) - label = '%s | %s' % (line[1], line[0].strip()) + label = f'{line[1]} | {line[0].strip()}' val = { 'cc': ["'%s'" % a for a in line[1].split(',')], 'dnuper': line[2] @@ -790,7 +790,7 @@ def getFeaturesFromSqlQuery(self, layer, filterExpression=None, attributes='*', features = [] if rowCount > 0: fids = [str(a[0]) for a in data] - exp = ' "%s" IN ( %s ) ' % ( + exp = ' "{}" IN ( {} ) '.format( attributes[0], ','.join(fids) ) @@ -880,7 +880,7 @@ def onSearchItemChoose(self, key, label, value): if features: self.qc.updateLog( - u"%s parcelle(s) trouvée(s) pour '%s'" % ( + "{} parcelle(s) trouvée(s) pour '{}'".format( len(features), label ) @@ -907,7 +907,7 @@ def onNonSearchItemChoose(self, key): ckey = child['key'] fkey = child['fkey'] if feature: - filterExpression = "%s = '%s' AND lot = '%s'" % (fkey, feature[fkey], feature['lot']) + filterExpression = "{} = '{}' AND lot = '{}'".format(fkey, feature[fkey], feature['lot']) self.setupSearchCombobox(ckey, filterExpression, 'sql') else: if child['getIfNoFeature']: @@ -938,7 +938,7 @@ def onSearchItemReset(self, key): self.searchComboBoxes[key]['widget'].setCurrentIndex(0) self.searchComboBoxes[key]['widget'].lineEdit().selectAll() self.searchComboBoxes[key]['widget'].lineEdit().setFocus() - self.searchComboBoxes[key]['widget'].lineEdit().setText(u'') + self.searchComboBoxes[key]['widget'].lineEdit().setText('') def onSearchItemFocus(self, key): """ @@ -1092,7 +1092,7 @@ def setIdentifierToChosenItem(self, key): parcelle_dialog.show() else: - self.qc.updateLog(u'Aucune parcelle sélectionnée !') + self.qc.updateLog('Aucune parcelle sélectionnée !') def printInfosProprietaires(self): """ @@ -1102,7 +1102,7 @@ def printInfosProprietaires(self): document = QTextDocument() document.setHtml( - "

Parcelle : %s

%s
" % ( + "

Parcelle : {}

{}
".format( self.textEdit.toolTip(), self.textEdit.toHtml() ) ) @@ -1127,7 +1127,7 @@ def printInfosProprietaires(self): def copyInfosProprietaires(self): QApplication.clipboard().setText( - "

Parcelle : %s

%s
" % ( + "

Parcelle : {}

{}
".format( self.textEdit.toolTip(), self.textEdit.toHtml() ) ) @@ -1150,7 +1150,7 @@ def saveInfosProprietaires(self): fileName = dlgFile.selectedFiles()[0] with open(fileName, 'w', encoding="utf8", errors="surrogateescape") as inFile: inFile.write( - "

Parcelle : %s

%s
" % ( + "

Parcelle : {}

{}
".format( self.textEdit.toolTip(), self.textEdit.toHtml() ) ) diff --git a/cadastre/edigeo_parser.py b/cadastre/edigeo_parser.py index 24821041..bf53f89b 100644 --- a/cadastre/edigeo_parser.py +++ b/cadastre/edigeo_parser.py @@ -60,7 +60,7 @@ def total_size(self) -> int: return size def __str__(self): - return '{} ({})'.format(self.insee, self.departement) + return f'{self.insee} ({self.departement})' class Parser: diff --git a/cadastre/getmultipolygonfromvec.py b/cadastre/getmultipolygonfromvec.py index 660460d4..013ce05b 100644 --- a/cadastre/getmultipolygonfromvec.py +++ b/cadastre/getmultipolygonfromvec.py @@ -52,7 +52,7 @@ def __features__(self): """ Find features with more than 1 faces """ if not self.path: return False - f = open(self.path, 'r', encoding='ISO-8859-1') + f = open(self.path, encoding='ISO-8859-1') if not f: return False osRTY = '' @@ -100,7 +100,7 @@ def __layers__(self): """ Find the layers for the features """ if not self.path: return False - f = open(self.path, 'r') + f = open(self.path) if not f: return False osRTY = '' @@ -131,7 +131,7 @@ def __arcs__(self): """ Find the arcs for the faces """ if not self.path: return False - f = open(self.path, 'r') + f = open(self.path) if not f: return False osRTY = '' @@ -183,7 +183,7 @@ def __coords__(self): """ Find the coords for the arcs """ if not self.path: return False - f = open(self.path, 'r') + f = open(self.path) if not f: return False osRTY = '' @@ -210,7 +210,7 @@ def __nodes__(self): """ Find the noeuds for the arcs """ if not self.path: return False - f = open(self.path, 'r') + f = open(self.path) if not f: return False osRTY = '' diff --git a/cadastre/infra/processing_doc.py b/cadastre/infra/processing_doc.py index 5ecbf24e..a3f1a2a8 100755 --- a/cadastre/infra/processing_doc.py +++ b/cadastre/infra/processing_doc.py @@ -165,7 +165,7 @@ def generate_processing_doc(): # NOQA C901 help_string=alg.shortHelpString() if alg.shortHelpString() else '', parameters=param_markdown if param_markdown else 'No parameter', outputs=output_markdown if output_markdown else 'No output', - img='./{}'.format(basename(output_screen)), + img=f'./{basename(output_screen)}', algo_id=alg.id(), ) diff --git a/cadastre/logger.py b/cadastre/logger.py index cf6e9e7f..c23b2f3f 100644 --- a/cadastre/logger.py +++ b/cadastre/logger.py @@ -82,7 +82,7 @@ def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() - Logger.info("{} ran in {}s".format(func.__name__, round(end - start, 2))) + Logger.info(f"{func.__name__} ran in {round(end - start, 2)}s") return result return wrapper @@ -94,7 +94,7 @@ def log_output_value(func): @functools.wraps(func) def wrapper(*args, **kwargs): result = func(*args, **kwargs) - Logger.info("{} output is {} for parameter {}".format(func.__name__, result, str(args))) + Logger.info(f"{func.__name__} output is {result} for parameter {str(args)}") return result return wrapper diff --git a/cadastre/processing/algorithms/config.py b/cadastre/processing/algorithms/config.py index bd6a800a..c613c781 100644 --- a/cadastre/processing/algorithms/config.py +++ b/cadastre/processing/algorithms/config.py @@ -145,4 +145,4 @@ def shortHelpString(self): ) def helpUrl(self) -> str: - return "{}/processing/#configuration-du-projet".format(URL_DOCUMENTATION) + return f"{URL_DOCUMENTATION}/processing/#configuration-du-projet" diff --git a/cadastre/processing/algorithms/edigeo_downloader.py b/cadastre/processing/algorithms/edigeo_downloader.py index c27a735f..2fe5924f 100644 --- a/cadastre/processing/algorithms/edigeo_downloader.py +++ b/cadastre/processing/algorithms/edigeo_downloader.py @@ -105,7 +105,7 @@ def processAlgorithm(self, parameters, context, feedback): directory = Path(self.parameterAsString(parameters, self.DOSSIER, context)) if not directory.exists(): - feedback.pushDebugInfo("Création du répertoire {}".format(directory)) + feedback.pushDebugInfo(f"Création du répertoire {directory}") os.makedirs(directory, exist_ok=True) filtre = [c.strip() for c in filtre.split(',')] @@ -125,7 +125,7 @@ def processAlgorithm(self, parameters, context, feedback): commune = Commune(commune_insee, date=date, base_url=url) if not self.download_commune(directory, commune, filtre, multi_feedback, context): - multi_feedback.reportError("Erreur sur la commune {}".format(commune.insee)) + multi_feedback.reportError(f"Erreur sur la commune {commune.insee}") break if multi_feedback.isCanceled(): @@ -140,9 +140,9 @@ def processAlgorithm(self, parameters, context, feedback): multi_feedback.pushInfo("\n") multi_feedback.pushInfo("\n") - multi_feedback.pushInfo("Téléchargement terminé pour {} communes".format(len(communes))) - multi_feedback.pushInfo("{} feuilles".format(self.results[self.NB_FEUILLES])) - multi_feedback.pushInfo("dans {}".format(str(directory))) + multi_feedback.pushInfo(f"Téléchargement terminé pour {len(communes)} communes") + multi_feedback.pushInfo(f"{self.results[self.NB_FEUILLES]} feuilles") + multi_feedback.pushInfo(f"dans {str(directory)}") multi_feedback.pushInfo("\n") multi_feedback.pushInfo("\n") return self.results @@ -151,10 +151,10 @@ def download_commune(self, directory: Path, commune: Commune, filtre: list, feed """ Télécharger une commune. """ commune_directory = directory.joinpath(commune.insee) if commune_directory.exists(): - feedback.reportError("Omission de {}, le répertoire existe déjà.".format(commune.insee)) + feedback.reportError(f"Omission de {commune.insee}, le répertoire existe déjà.") return False - feedback.pushInfo("Téléchargement de l'index concernant {}".format(commune.insee)) + feedback.pushInfo(f"Téléchargement de l'index concernant {commune.insee}") feedback.pushDebugInfo(commune.url) params = { @@ -170,12 +170,12 @@ def download_commune(self, directory: Path, commune: Commune, filtre: list, feed ) parser = Parser(data['OUTPUT'], commune, feuille_filter=filtre) parser.parse() - feedback.pushInfo(" {} feuilles".format(parser.count)) + feedback.pushInfo(f" {parser.count} feuilles") for feuille in parser.feuilles: feedback.pushInfo(feuille.name) if not commune_directory.exists(): - feedback.pushDebugInfo("Création du répertoire {}".format(commune)) + feedback.pushDebugInfo(f"Création du répertoire {commune}") os.makedirs(commune_directory, exist_ok=True) for feuille in parser.feuilles: @@ -189,7 +189,7 @@ def download_commune(self, directory: Path, commune: Commune, filtre: list, feed @staticmethod def download_feuille(commune, feuille, directory, feedback, context) -> bool: - feedback.pushInfo("Téléchargement de {} {}".format(commune.insee, feuille.name)) + feedback.pushInfo(f"Téléchargement de {commune.insee} {feuille.name}") params = { 'URL': commune.url_feuille(feuille), 'OUTPUT': str(directory.joinpath(feuille.link).absolute()), @@ -218,4 +218,4 @@ def shortHelpString(self): ) def helpUrl(self): - return "{}/extension-qgis/donnees/#edigeo".format(URL_DOCUMENTATION) + return f"{URL_DOCUMENTATION}/extension-qgis/donnees/#edigeo" diff --git a/cadastre/scripts/pyogr/ogr2ogr.py b/cadastre/scripts/pyogr/ogr2ogr.py index 3b085544..d5fd789d 100755 --- a/cadastre/scripts/pyogr/ogr2ogr.py +++ b/cadastre/scripts/pyogr/ogr2ogr.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- #/****************************************************************************** # * $Id$ # * @@ -48,7 +47,7 @@ ############################################################################### -class ScaledProgressObject(object): +class ScaledProgressObject: def __init__(self, min, max, cbk, cbk_data = None): self.min = min self.max = max @@ -104,7 +103,7 @@ def TermProgress( dfComplete, pszMessage, pProgressArg ): return True -class TargetLayerInfo(object): +class TargetLayerInfo: def __init__(self): self.poDstLayer = None self.poCT = None @@ -112,7 +111,7 @@ def __init__(self): self.panMap = None self.iSrcZField = None -class AssociatedLayers(object): +class AssociatedLayers: def __init__(self): self.poSrcLayer = None self.psInfo = None @@ -737,7 +736,7 @@ def ogr2ogr( #/* -------------------------------------------------------------------- */ poODS = poDriver.CreateDataSource( pszDestDataSource, options = papszDSCO ) if poODS is None: - print( "%s driver failed to create %s" % (pszFormat, pszDestDataSource )) + print( f"{pszFormat} driver failed to create {pszDestDataSource}") return False #/* -------------------------------------------------------------------- */ @@ -920,7 +919,7 @@ def ogr2ogr( if CSLFindString(papszLayers, poLayer.GetName()) >= 0: if pszWHERE is not None: if poLayer.SetAttributeFilter( pszWHERE ) != 0: - print("FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n" % (pszWHERE, poLayer.GetName()) ) + print(f"FAILURE: SetAttributeFilter({pszWHERE}) on layer '{poLayer.GetName()}' failed.\n" ) if not bSkipFailures: return False diff --git a/cadastre/scripts/pyogr/ogrds.py b/cadastre/scripts/pyogr/ogrds.py index 6d674934..54f25e59 100644 --- a/cadastre/scripts/pyogr/ogrds.py +++ b/cadastre/scripts/pyogr/ogrds.py @@ -1,7 +1,7 @@ import ogr -class OgrDs(object): +class OgrDs: def __init__(self, format, ds): self.open(format, ds) diff --git a/cadastre/scripts/pyogr/ogrinfo.py b/cadastre/scripts/pyogr/ogrinfo.py index dee05db7..f1db8ba1 100755 --- a/cadastre/scripts/pyogr/ogrinfo.py +++ b/cadastre/scripts/pyogr/ogrinfo.py @@ -406,7 +406,7 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ): if nGeomFieldCount > 1: for iGeom in range(nGeomFieldCount): poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom) - print( "Geometry (%s): %s" % (poGFldDefn.GetNameRef(), ogr.GeometryTypeToName( poGFldDefn.GetType() ) )) + print( f"Geometry ({poGFldDefn.GetNameRef()}): {ogr.GeometryTypeToName( poGFldDefn.GetType() )}") else: print( "Geometry: %s" % ogr.GeometryTypeToName( poDefn.GetGeomType() ) ) @@ -417,11 +417,11 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ): poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom) oExt = poLayer.GetExtent(True, geom_field = iGeom, can_return_null = True) if oExt is not None: - print("Extent (%s): (%f, %f) - (%f, %f)" % (poGFldDefn.GetNameRef(), oExt[0], oExt[2], oExt[1], oExt[3])) + print(f"Extent ({poGFldDefn.GetNameRef()}): ({oExt[0]:f}, {oExt[2]:f}) - ({oExt[1]:f}, {oExt[3]:f})") else: oExt = poLayer.GetExtent(True, can_return_null = True) if oExt is not None: - print("Extent: (%f, %f) - (%f, %f)" % (oExt[0], oExt[2], oExt[1], oExt[3])) + print(f"Extent: ({oExt[0]:f}, {oExt[2]:f}) - ({oExt[1]:f}, {oExt[3]:f})") if nGeomFieldCount > 1: for iGeom in range(nGeomFieldCount): @@ -430,7 +430,7 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ): pszWKT = "(unknown)" else: pszWKT = poGFldDefn.GetSpatialRef().ExportToPrettyWkt() - print( "SRS WKT (%s):\n%s" % (poGFldDefn.GetNameRef(), pszWKT) ) + print( f"SRS WKT ({poGFldDefn.GetNameRef()}):\n{pszWKT}" ) else: if poLayer.GetSpatialRef() is None: pszWKT = "(unknown)" @@ -492,7 +492,7 @@ def DumpReadableFeature( poFeature, options = None ): poFDefn = poDefn.GetFieldDefn(iField) - line = " %s (%s) = " % ( \ + line = " {} ({}) = ".format( \ poFDefn.GetNameRef(), \ ogr.GetFieldTypeName(poFDefn.GetType()) ) @@ -533,7 +533,7 @@ def DumpReadableGeometry( poGeometry, pszPrefix, options ): if 'DISPLAY_GEOMETRY' in options and EQUAL(options['DISPLAY_GEOMETRY'], 'SUMMARY'): - line = ("%s%s : " % (pszPrefix, poGeometry.GetGeometryName() )) + line = (f"{pszPrefix}{poGeometry.GetGeometryName()} : ") eType = poGeometry.GetGeometryType() if eType == ogr.wkbLineString or eType == ogr.wkbLineString25D: line = line + ("%d points" % poGeometry.GetPointCount()) @@ -568,11 +568,7 @@ def DumpReadableGeometry( poGeometry, pszPrefix, options ): print(line) for ig in range(poGeometry.GetGeometryCount()): subgeom = poGeometry.GetGeometryRef(ig) - from sys import version_info - if version_info >= (3,0,0): - exec('print("", end=" ")') - else: - exec('print "", ') + exec('print("", end=" ")') DumpReadableGeometry( subgeom, pszPrefix, options) else: print(line) @@ -580,7 +576,7 @@ def DumpReadableGeometry( poGeometry, pszPrefix, options ): elif 'DISPLAY_GEOMETRY' not in options or EQUAL(options['DISPLAY_GEOMETRY'], 'yes') \ or EQUAL(options['DISPLAY_GEOMETRY'], 'WKT'): - print("%s%s" % (pszPrefix, poGeometry.ExportToWkt() )) + print(f"{pszPrefix}{poGeometry.ExportToWkt()}") return diff --git a/cadastre/server/cadastre_server.py b/cadastre/server/cadastre_server.py index 77fc1734..876afc24 100644 --- a/cadastre/server/cadastre_server.py +++ b/cadastre/server/cadastre_server.py @@ -22,7 +22,7 @@ class CadastreServer: def __init__(self, server_iface: QgsServerInterface) -> None: - Logger.info('Init server version "{}"'.format(version())) + Logger.info(f'Init server version "{version()}"') cache_dir_str = os.getenv('QGIS_CADASTRE_CACHE_DIR') if not cache_dir_str: @@ -32,7 +32,7 @@ def __init__(self, server_iface: QgsServerInterface) -> None: self.cache_dir = Path(cache_dir_str) self.cache_dir.mkdir(mode=0o750, parents=True, exist_ok=True) - Logger.info('Cache directory set to {}'.format(cache_dir_str)) + Logger.info(f'Cache directory set to {cache_dir_str}') reg = server_iface.serviceRegistry() reg.registerService(CadastreService(cache_dir=self.cache_dir)) diff --git a/cadastre/server/cadastre_service.py b/cadastre/server/cadastre_service.py index 7408cf9d..35a03fb0 100644 --- a/cadastre/server/cadastre_service.py +++ b/cadastre/server/cadastre_service.py @@ -37,7 +37,7 @@ def __init__(self, code: int, msg: str) -> None: super().__init__(msg) self.msg = msg self.code = code - Logger.critical("Cadastre request error {}: {}".format(code, msg)) + Logger.critical(f"Cadastre request error {code}: {msg}") def format_response(self, response: QgsServerResponse) -> None: """ Format error response @@ -189,7 +189,7 @@ def create_pdf(self, params: Dict[str, str], response: QgsServerResponse, projec all_cities ) - Logger.debug("comptecommunal = {}".format(compte_communal)) + Logger.debug(f"comptecommunal = {compte_communal}") # Export PDF qex = CadastreExport(project, res.layer, res.type, compte_communal, res.geo_parcelle) @@ -200,13 +200,13 @@ def create_pdf(self, params: Dict[str, str], response: QgsServerResponse, projec if not paths: raise CadastreError(424, 'An error occurred while generating the PDF') - Logger.debug("export_as_pdf(), paths: {}".format(paths)) + Logger.debug(f"export_as_pdf(), paths: {paths}") tokens = [] for path in map(Path, paths): uid = uuid4() - Logger.debug("Item path: {}".format(path)) + Logger.debug(f"Item path: {path}") new_path = self.cache_dir / ('%s.pdf' % uid.hex) path.rename(new_path) @@ -289,7 +289,7 @@ def get_param(name: str, allowed_values: Sequence[str] = None) -> str: it = layer.getFeatures(req) feat = QgsFeature() if not it.nextFeature(feat): - raise CadastreError(404, "Feature not found for parcelle '%s' in layer '%s'" % (p_parcelle, p_layer)) + raise CadastreError(404, f"Feature not found for parcelle '{p_parcelle}' in layer '{p_layer}'") # Get layer connection parameters connection_params = cadastre_common.getConnectionParameterFromDbLayer(layer) @@ -312,9 +312,9 @@ def get_pdf(self, params: Dict[str, str], response: QgsServerResponse) -> None: if not ptoken: raise CadastreError(400, "Missing parameter: token") - path = self.cache_dir / '{}.pdf'.format(ptoken) + path = self.cache_dir / f'{ptoken}.pdf' - Logger.debug("GetPDF = path is {}".format(path.as_posix())) + Logger.debug(f"GetPDF = path is {path.as_posix()}") if not path.exists(): raise CadastreError(404, "PDF not found") diff --git a/cadastre/tests/runner.py b/cadastre/tests/runner.py index 4380441c..5a9cc193 100644 --- a/cadastre/tests/runner.py +++ b/cadastre/tests/runner.py @@ -13,11 +13,11 @@ def pytest_report_header(config): """Used by PyTest and Unittest.""" - message = "QGIS : {}\n".format(Qgis.QGIS_VERSION_INT) + message = f"QGIS : {Qgis.QGIS_VERSION_INT}\n" message += "Python GDAL : {}\n".format(gdal.VersionInfo("VERSION_NUM")) - message += "Python : {}\n".format(sys.version) + message += f"Python : {sys.version}\n" # message += 'Python path : {}'.format(sys.path) - message += "QT : {}".format(Qt.QT_VERSION_STR) + message += f"QT : {Qt.QT_VERSION_STR}" return message @@ -29,21 +29,21 @@ def _run_tests(test_suite, package_name, pattern): count = test_suite.countTestCases() print("######## Environment ########") print(pytest_report_header(None)) - print("{} tests has been discovered in {} with pattern {}".format(count, package_name, pattern)) + print(f"{count} tests has been discovered in {package_name} with pattern {pattern}") print("######## Running tests ########") results = unittest.TextTestRunner(verbosity=2).run(test_suite) print("######## Summary ########") - print("Errors : {}".format(len(results.errors))) - print("Failures : {}".format(len(results.failures))) - print("Expected failures : {}".format(len(results.expectedFailures))) - print("Unexpected successes : {}".format(len(results.unexpectedSuccesses))) - print("Skip : {}".format(len(results.skipped))) + print(f"Errors : {len(results.errors)}") + print(f"Failures : {len(results.failures)}") + print(f"Expected failures : {len(results.expectedFailures)}") + print(f"Unexpected successes : {len(results.unexpectedSuccesses)}") + print(f"Skip : {len(results.skipped)}") successes = ( results.testsRun - ( len(results.errors) + len(results.failures) + len(results.expectedFailures) + len(results.unexpectedSuccesses) + len(results.skipped))) - print("Successes : {}".format(successes)) - print("TOTAL : {}".format(results.testsRun)) + print(f"Successes : {successes}") + print(f"TOTAL : {results.testsRun}") def test_package(package=None, pattern="test_*.py"): @@ -58,7 +58,7 @@ def test_package(package=None, pattern="test_*.py"): """ pattern_environment = os.environ.get('TEST_PATTERN') if pattern_environment and pattern_environment != 'default_pattern': - print("Pattern from environment : {}".format(pattern_environment)) + print(f"Pattern from environment : {pattern_environment}") pattern = pattern_environment if package is None: diff --git a/cadastre/tools.py b/cadastre/tools.py index f9c42675..be18a4a6 100644 --- a/cadastre/tools.py +++ b/cadastre/tools.py @@ -33,7 +33,7 @@ def wrap(*args): time1 = time.time() ret = f(*args) time2 = time.time() - print('{:s} function took {:.3f} ms'.format(f.__name__, (time2 - time1) * 1000.0)) + print(f'{f.__name__:s} function took {(time2 - time1) * 1000.0:.3f} ms') return ret @@ -80,7 +80,7 @@ def next_git_tag(): return 'next' versions = tag.split('.') - text = '{}.{}.{}-pre'.format(versions[0], versions[1], int(versions[2]) + 1) + text = f'{versions[0]}.{versions[1]}.{int(versions[2]) + 1}-pre' return text @@ -93,4 +93,4 @@ def set_window_title() -> str: # return 'branch {}, commit {}, next {}'.format( # version, current_git_hash(), next_git_tag()) - return 'next {}'.format(next_git_tag()) + return f'next {next_git_tag()}' diff --git a/tests/conftest.py b/tests/conftest.py index 7374413d..029e2493 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -156,7 +156,7 @@ def to_int(ver): major += 1 if rev > 99: rev = 99 - return int("{:d}{:02d}{:02d}".format(major,minor,rev)) + return int(f"{major:d}{minor:02d}{rev:02d}") version = to_int(Qgis.QGIS_VERSION.split('-')[0]) @@ -177,7 +177,7 @@ def find_plugins(pluginpath: str) -> Generator[str,None,None]: cp = configparser.ConfigParser() try: - with open(metadatafile, mode='rt') as f: + with open(metadatafile) as f: cp.read_file(f) if not cp['general'].getboolean('server'): logging.critical("%s is not a server plugin", plugin) @@ -237,7 +237,7 @@ def install_logger_hook( verbose: bool=False ) -> None: # Add a hook to qgis message log def writelogmessage(message, tag, level): - arg = '{}: {}'.format( tag, message ) + arg = f'{tag}: {message}' if level == Qgis.Warning: LOGGER.warning(arg) elif level == Qgis.Critical: