Giter VIP home page Giter VIP logo

jonathanwillitts / common-qgis-2-to-3-plugin-fixes Goto Github PK

View Code? Open in Web Editor NEW
13.0 4.0 3.0 22 KB

Contains fixes to common PyQGIS 2 to 3 plugin migration issues, collated whilst migrating a QGIS 2.18 plugin to QGIS 3.2 (and then to 3.4). Also provides some recommendations on the migration process.

License: Creative Commons Attribution 4.0 International

qgis-plugin qgis3-plugin qgis2-plugin qgis qgis3 qgis2 pyqgis

common-qgis-2-to-3-plugin-fixes's Introduction

Fixes to common problems when migrating QGIS plugins from v2.18 to v3.x

Below is a list of fixes to common PyQGIS migration issues I collated whilst migrating a QGIS 2.18 plugin to QGIS 3.2 (and then to 3.4). I documented each error message and fix to make things easier if I came across the same issue again, and subsequently figured it may be of user to others who were migrating their plugins too.

Table of contents

Error messages and fixes

Details of error messages are documented as sub-headings, with fixes and examples for each listed underneath. Where possible I've included links back to relevant documentation too.

Error messages are listed alphabetically, and as such are organised by error type (AttributeError, NameError, TypeError).


Attribute errors:

AttributeError: type object 'Qgis' has no attribute 'Line'

AttributeError: type object 'Qgis' has no attribute 'WKBPoint'

AttributeError: type object 'Qgis' has no attribute 'WKBPolygon'

To fix: replace Qgis.<Old Type> with QgsWkbTypes.<New Type>

e.g.

QGis.Line

# becomes
QgsWkbTypes.LineGeometry


Qgis.WKBPolygon 

# becomes
QgsWkbTypes.Polygon


Qgis.WKBPoint

# becomes
QgsWkbTypes.Point

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsWkbTypes

and QGIS breaking changes 'General changes' section


AttributeError: type object 'QgsGeometry' has no attribute 'fromMultiPolyline'

To fix: replace .fromMultiPolyline([qgs_point_list]) with .fromMultiPolylineXY([qgs_pointXY_list])

e.g.

QgsGeometry.fromMultiPolyline(qgs_point_list)

# becomes
QgsGeometry.fromMultiPolylineXY(qgs_point_xy_list)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsGeometry.fromMultiPolylineXY()

and QGIS breaking changes for QgsGeometry


AttributeError: type object 'QgsMessageBar' has no attribute 'INFO'

AttributeError: type object 'QgsMessageBar' has no attribute 'WARNING'

AttributeError: type object 'QgsMessageBar' has no attribute 'CRITICAL'

AttributeError: type object 'QgsMessageBar' has no attribute 'SUCCESS'

To fix: replace QgsMessageBar.<MessageLevel> with Qgis.<MessageLevel>

e.g.

QgsMessageBar.INFO

# becomes
Qgis.Info


QgsMessageBar.WARNING

# becomes
Qgis.Warning


QgsMessageBar.CRITICAL

# becomes
Qgis.Critical


QgsMessageBar.SUCCESS

# becomes
Qgis.Success

See also: QGIS API doc for Qgis.MessageLevel

and QGIS breaking changes for QgsMessageLevel


AttributeError: type object 'QgsSymbolLayerRegistry' has no attribute 'instance'

To fix: replace QgsSymbolLayerRegistry.instance() with QgsApplication.symbolLayerRegistry()

e.g.

QgsSymbolLayerRegistry.instance()

# becomes
QgsApplication.symbolLayerRegistry()

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsApplication.symbolLayerRegistry()

and QGIS breaking changes for QgsSymbolLayerRegistry


AttributeError: 'QgisInterface' object has no attribute 'legendInterface'

To fix: reference the layer (by id) within the layerTreeRoot, and set visibility there.

e.g.

iface.legendInterface().setLayerVisible(layer, False)

# becomes
QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setItemVisibilityChecked(False)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsLayerTreeNode.setItemVisibilityChecked()

and QGIS breaking changes 'Removed Classes' section

and this GIS Stack Exchange answer


AttributeError: 'QgsLayerTree' object has no attribute 'selectedLayers'

To fix: replace .legendInterface() with .layerTreeView()

e.g.

iface.legendInterface().selectedLayers()

# becomes
iface.layerTreeView().selectedLayers()

See also: QGIS Python API (PyQGIS) doc for qgis.gui.QgsLayerTreeView.selectedLayers()

and QGIS breaking changes for QgsGeometry


AttributeError: type object 'QgsGeometry' has no attribute 'fromPoint'

To fix: replace .fromPoint() with .fromPointXY()

e.g.

QgsGeometry.fromPoint(qgs_point)

# becomes
QgsGeometry.fromPointXY(qgs_point_xy)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsGeometry.fromPointXY()

and QGIS breaking changes for QgsGeometry


AttributeError: 'QgsGeometry' object has no attribute 'exportToWkt'

To fix: replace .exportToWkt() with .asWkt()

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsGeometry.asWkt()

and QGIS breaking changes for QgsGeometry


AttributeError: 'QgsPalLayerSettings' object has no attribute 'readFromLayer'

To fix: refer to this GIS Stack Exchange answer

and QGIS breaking changes for QgsPalLayerSettings


AttributeError: 'QgsVectorLayer' object has no attribute 'setDisplayField'

To fix: replace .setDisplayField(html) with .setMapTipTemplate(html)

e.g.

layer.setDisplayField(html)

# becomes
layer.setMapTipTemplate(html)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsVectorLayer.setMapTipTemplate()

and QGIS breaking changes for QgsVectorLayer


AttributeError: 'QgsVectorLayer' object has no attribute 'setLayerTransparency'

To fix: replace .setLayerTransparancy(percentage) with .setOpacity(percentage / 100)

e.g.

layer.setLayerTransparency(60)

# becomes
layer.setOpacity(0.6)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsVectorLayer.setOpacity()

and QGIS breaking changes for QgsVectorLayer


AttributeError: 'QgsVectorLayer' object has no attribute 'rendererV2'

To fix: replace .rendererV2().symbols() with .renderer().symbol() and access the symbol directly

e.g.

symbols = layer.rendererV2().symbols()
symbol = symbols[0]

# becomes
symbol = layer.renderer().symbol()

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsSingleSymbolRenderer.symbol()

and QGIS Python API (PyQGIS) doc for qgis.core.QgsVectorLayer.setRenderer()

and QGIS breaking changes 'Renamed Methods' section


AttributeError: 'QgsVectorLayer' object has no attribute 'setRendererV2'

To fix: replace .setRendererV2(renderer) with .setRenderer(renderer)

e.g.

layer.setRendererV2(renderer)

# becomes
layer.setRenderer(renderer)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsVectorLayer.setRenderer()


Name errors:

NameError: name 'QGis' is not defined

To fix: replace QGis.xxx with Qgis.xxx (note change in case from QG to Qg)

e.g.

from qgis.core import QGis
QGis.xxx

# becomes 
from qgis.core import Qgis
Qgis.xxx

See also: QGIS API doc for Qgis

and QGIS breaking changes for Qgis


Type errors:

TypeError: QgsCoordinateTransform(): arguments did not match any overloaded call:

  overload 1: too many arguments
  overload 2: not enough arguments
  overload 3: not enough arguments
  overload 4: not enough arguments
  overload 5: argument 1 has unexpected type 'QgsCoordinateReferenceSystem'

To fix: add QgsProject.instance() to QgsCoordinateTransform() call

e.g.

xform = QgsCoordinateTransform(src_crs, dest_crs)


# becomes
xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance())

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsCoordinateTransform

and QGIS breaking changes for QgsCoordinateTransform


TypeError: QgisInterface.newProject(): 'thePromptToSaveFlag' is not a valid keyword argument

To fix: replace thePromptToSaveFlag with promptToSaveFlag

e.g.

iface.newProject(thePromptToSaveFlag=False)

# becomes
iface.newProject(promptToSaveFlag=False)

See also: QGIS Python API (PyQGIS) doc for qgis.gui.QgisInterface.newProject()


TypeError: QgsProject.read(): arguments did not match any overloaded call:

overload 1: argument 1 has unexpected type 'QFileInfo'
overload 2: too many arguments

To fix: remove QFileInfo and just pass string to QgsProject.read()

e.g.

project.read(QFileInfo(project_file))

# becomes
project.read(project_file)

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsProject.read()

and QGIS breaking changes for QgsProject


TypeError: QgsRectangle(): arguments did not match any overloaded call:

  overload 1: too many arguments
  overload 2: argument 1 has unexpected type 'QgsPoint'
  overload 3: argument 1 has unexpected type 'QgsPoint'
  overload 4: argument 1 has unexpected type 'QgsPoint'
  overload 5: argument 1 has unexpected type 'QgsPoint'

To fix: replace instances of QgsPoint with QgsPointXY

e.g.

QgsRectangle(QgsPoint(x_min, y_min), QgsPoint(x_max, y_max)))

# becomes
QgsRectangle(QgsPointXY(x_min, y_min), QgsPointXY(x_max, y_max)))

See also: QGIS Python API (PyQGIS) doc for qgis.core.QgsRectangle

and QGIS breaking changes 'Renamed Classes' section


TypeError: QgsRubberBand.addPoint(): argument 1 has unexpected type 'QgsPoint'

To fix: replace instances of QgsPoint with QgsPointXY

e.g.

QgsPoint(..., ...)

# becomes
QgsPointXY(..., ...)

See also: QGIS Python API (PyQGIS) doc for qgis.gui.QgsRubberBand.addPoint()

and QGIS breaking changes 'Renamed Classes' section

See also:

If the message you are getting when trying to migrate your plugin is not on this page, you can refer to:

I also found the First Aid QGIS plugin quite useful throughout the process, see:
First Aid's GitHub page and their blog post introducing it for more details.

Contributions:

Contributions to improve this document are welcome, whether in the form or corrections, changes, additional entries, or anything else you see fit. Please submit a pull request.

License:

Creative Commons License
common-qgis-2-to-3-plugin-fixes is licensed under a Creative Commons Attribution 4.0 International License.

common-qgis-2-to-3-plugin-fixes's People

Contributors

jonathanwillitts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.