0.6.0 migration notes
Project shape (decision-43). A 0.6 project carries no
metadata.txt, classFactory or webview.py; qgis-sdk check reports the
old files as META001/ENTRY002. To migrate a 0.5 project:
- Delete
<plugin>/metadata.txtand<plugin>/webview.py; removeclassFactory, thebuild_context/notifications glue and the desktop wrapper class from<plugin>/plugin.pyand thefrom .plugin import classFactoryline from<plugin>/__init__.py. What remains is the@pluginclass (plus your own modules). - Add to
pyproject.toml:[project]name,version,description,authorsanddependencies = ["qgis-sdk-runtime>=0.6,<0.7"];[tool.qgis-sdk] plugin = "<package>.plugin:<Class>",qgis-minimum-version,experimental; any extrametadata.txtkeys under[tool.qgis-sdk.metadata]; with a page,[tool.qgis-sdk.web] placement = "dock" | "dialog"andgrants = [...]naming the host operations the page calls (the formerwebview.pyregistered them all; list the ones you use -qgis-sdk checknames an unknown id). - In the project’s own tests, bind the entry point the way
builddoes:classFactory = host("<package>.plugin:<Class>", placement=...)fromqgis_sdk.adapters.desktop.
qgis-sdk build and qgis-sdk dev then produce metadata.txt and
classFactory themselves; see Desktop host above.
0.6.0 of qgis-sdk-runtime changes how a job is written
(decision-38)
and how optional services are reached on every context
(decision-39).
Everything about submission, handles, delivery and ownership is as
in 0.5.
-
require_<name>()is gone; the attribute refuses by name. OnPluginContext,UiContext,AlgorithmContextandJobContextevery optional service (desktop,network,layers,project,settings,styles,algorithms,workers) is now typed as the service itself and reading one the host did not provide raisesQgisSdkUnsupportedCapabilityError(capability=<name>)— the same errorrequire_<name>()raised, now onctx.workers.offload(...)directly. Replacectx.require_workers()withctx.workers,ctx.require_native()withctx.desktop, and so on; constructor keyword arguments are unchanged. Code that probed a slot (if ctx.network is not None:) usesctx.has("network")orctx.capabilitiesinstead - the attribute no longer evaluates toNone, andhas()raisesValueErrorfor a name the context does not carry. Contexts are no longer dataclasses: they stay immutable (AttributeErroron assignment) butdataclasses.replace/asdictdo not apply to them. -
@jobdecorates a function, not a class. The first parameter is theJobContextthe runtime injects, the remaining parameters are typed keyword inputs (defaults allowed, the same annotations an@actionaccepts) and the return annotation is the result.delaytakes the inputs as keywords and refuses a submission that does not fit the signature withQgisSdkJobRejectedErrorbefore anything is queued.ctx.jobs.delay(fn, **inputs)is the one-call spelling ofbindthendelay. The class form is refused by@jobandbindwith a message that names the change; see Migrating from the 0.5 class form for the side-by-side. -
JobDescriptiondescribes a signature.inputs_typeis gone;parameters,requiredandannotationsdescribe the keyword inputs andinputs_schemais their object schema (soto_dict()["inputs"]is the schema itself, not{"type": ...}).result_type/result_schemaare unchanged.describe(fn)answers for a@jobfunction; the refusal for an undecorated class now reads “describe requires a class declared with @plugin, or a function declared with @job or @provider.algorithm”.
Algorithms follow the same move (decision-42). Every rename, in one list:
@provider.algorithmdecorates a function, not a class.run(self, inputs: Request) -> Resultbecomesdef name(ctx: AlgorithmContext, **typed inputs) -> VectorLayerInfo; the request dataclass’s fields become the keyword parameters and the result dataclass’soutputbecomes the return value. The class form is refused with a message naming the change. The bare@algorithmdecorator andqgis_sdk.algorithms.algorithmare gone: a provider is the only container. A derived algorithm id is now the plain function name (no hash suffix); passid=to keep an old suffixed id. The class-form inspectorsdeclarations.RunSignature/describe_run_method(never in__all__) went with it;describe(fn)is the one inspector.invoke(Class, Request, algorithms=, project=, scope=, ...)becomesinvoke(function, ctx, **inputs): pass thePluginContext,JobContextorAlgorithmContextyou hold instead of its three services, and the inputs as keywords. It returns theVectorLayerInfodirectly;AlgorithmResultandresult.outputare gone.progress=,cancellation=andadd_to_project=keep their meaning; left out, progress and cancellation now come from a job or algorithm context.register_provider(...)/bridge.unregister()leave the plugin. Delete those lines frominitGui/unloadand addproviders = [tools]to the@pluginclass;PluginRuntime.start()/unload()register and remove them through the newprocessingcapability ofPluginContext(native_plugin_contextsuppliesNativeProcessing;qgis_sdk.testinggainsFakeProcessing).register_provideris no longer exported fromqgis_sdk.adapters.qgis.LayerInput,CrsInput,Metresare annotation aliases.Annotated[str, LayerInput()]becomesLayerInput(orAnnotated[str, LayerParameter()]),Annotated[str, CrsInput()]becomesCrsInput(CrsParameter),Annotated[float, Metres()]becomesMetres(MetresParameter); a bound moves toAnnotated[float, MetresParameter(minimum=..., maximum=...)]. This applies to@actionparameters too -qgis_sdk.uiandNativeFormsread the new markers.AlgorithmDescriptiondescribes a signature.inputs_typeis gone;parameters,required,annotationsandkindsdescribe the inputs,inputs_schemais their object schema, andgroup,provider_idandqualified_idare on the description.ProviderDescription.algorithmsis a tuple ofAlgorithmDescription(RegisteredAlgorithmis gone), andProvider.class_forisProvider.function_for.parameter_kinds(dataclass)isqgis_sdk.algorithms.parameter_kind(path, annotation);LAYER_PARAMETER,CRS_PARAMETER,METRES_PARAMETERlive there too.qgis_sdk.referenceis gone.BufferLayer/BufferResult/CentroidLayer/CentroidResulthave no runtime replacement: what a plugin computes is the plugin’s, so the two operations live in the example asexamples/simple/simple/algorithms.py(provider = Provider(id="simple", ...),buffer_layer,centroid_layer; toolbox idssimple:bufferandsimple:centroid). Copy that module into your plugin and rename the provider; the request modelsBufferRequest/CentroidRequestand the native service behindctx.algorithms.executeare unchanged. The runtime keeps no Processing algorithms of its own.- Contexts gain capabilities, additively.
JobContextcarriesalgorithmsandproject(JobService(..., algorithms=, project=)),AlgorithmContextcarriesproject, andPluginContextcarriesprocessing; all are optional constructor keywords that refuse by name when a host leaves them out. The wire contract,describe_pluginoutput andHOST_FINGERPRINTdo not move. - Desktop bindings and surfaces (decisions 45 and 55),
additively.
qgis_sdkexportstoolbar,menu,shortcutanddescribe_bindings;qgis_sdk.uiexportsDialog,DockandSurfacenext to the 0.5 form-field helpers, which moved toqgis_sdk.ui.form_fieldsand are re-exported fromqgis_sdk.uiunchanged.PluginContextgains an optionaluicapability (host()supplies it inside QGIS Desktop;qgis_sdk.testing.FakeUielsewhere) andUiContextgainsactionsandsettings. A plugin that places its ownQActions ininitGuikeeps working; moving them to@toolbar/@menuletshost()add and remove them with the plugin. See Desktop bindings and native surfaces.
qgis-sdk-tools 0.6.0 changes one thing in what qgis-sdk bridge generate
emits (decision-40):
- The generated contract error is
QgisSdkContractError(wasContractError). It still extendsError- the module stays import-free - and now carriescode: "contract_validation_failed"next tooperation. Regenerate the client (CI fails on the stale file anyway) and rename the class incatchclauses, or match onerror.code. The bridge package this release pairs with is@archont561/qgis-sdk0.4.0, whose own notes are in doc-13.