Skip to content

0.4.0 migration notes

0.4.0 closes the m-3 milestone (developer workflow and plugin packaging). It is a Python-only release, tag python-v0.4.0: no file under packages/qgis-sdk-typescript or packages/qgis-sdk-alias changed since ts-v0.3.0, so @archont561/qgis-sdk stays at 0.3.0 and generated web projects keep pinning it (decision-25). PLUGIN_DESCRIPTION_SCHEMA_VERSION, BRIDGE_PROTOCOL_VERSION and HOST_SCHEMA_VERSION all stay 1.

Two changes are breaking for code written against 0.3.0, each documented below with its one-line fix: the developer tools moved to qgis_sdk_tools (python -m qgis_sdk is gone, the pytest plugin path changed), and the runtime binds PluginContext as the ctx class attribute instead of passing it to the constructor. Everything a plugin imports from qgis_sdk.* at 0.3.0 is still there; the additions are listed. The notes are in reverse landing order.

  • Manifests: pyproject.toml and recipe.yaml carry 0.4.0; the bridge’s package.json and the alias carry 0.3.0. Verify with python scripts/release.py verify-versions --scope python --version 0.4.0 and --scope typescript --version 0.3.0.
  • qgis-sdk build is new; see “Building an installable ZIP”. Projects generated by qgis-sdk new now ignore dist/. A plugin that imports qgis_sdk_tools or qgis_sdk.testing from package code is refused at build time (DEP001/DEP002): those never ship.
  • qgis-sdk dev reloads on save and quiesces first. The Desktop bootstrap is now the importable module qgis_sdk_tools.devtools.reloader (policy, tested without QGIS) plus .devtools.bootstrap (the QGIS glue the --code probe reaches); plan_dev(...) and the qgis/desktop test plans put the SDK’s own import locations on the QGIS process’s PYTHONPATH. The request JSON gains watch (default True; --no-watch). New runtime API, additive: ResourceScope.on_quiesce(check, *, resume=None), scope.quiesce(), scope.resume(), PluginRuntime.quiesce() / resume(); QuiesceOutcome now lives in qgis_sdk.core.scope (still exported from qgis_sdk.core). A root JobService registers on its scope, and its blockers name the handle id (job sum#1 ...) instead of the scheduler’s number.
  • The developer tools moved to qgis_sdk_tools (decision-35, step 1). qgis_sdk.scaffold, qgis_sdk.check, qgis_sdk.cli, qgis_sdk.devtools, qgis_sdk.pytest_plugin and qgis_sdk.bridge.generate are now qgis_sdk_tools.scaffold, .check, .cli, .devtools, .pytest_plugin and qgis_sdk_tools.generate; FakeCliRuntime is qgis_sdk_tools.testing.FakeCliRuntime. python -m qgis_sdk is gone - use the qgis-sdk script or python -m qgis_sdk_tools. Generated projects now carry addopts = "-p qgis_sdk_tools.pytest_plugin"; a project generated from an unreleased build with the old path repoints that one line. The runtime API (qgis_sdk.* that a plugin imports) is unchanged; qgis_sdk.environment is new and holds the QGIS_SDK_DEV_SERVER / QGIS_SDK_TEST_TARGET names the generated webview.py and the tools share. The one wheel still ships both trees until the distributions split.
  • qgis-sdk test and qgis-sdk dev. New commands over qgis_sdk_tools.devtools (installs, testrun, dev) and the pytest plugin qgis_sdk_tools.pytest_plugin (both landed under qgis_sdk. and moved in the same release, see the previous note); see “Running tests” and “Developing against QGIS”. Projects generated by qgis-sdk new now carry a .gitignore, addopts = "-p qgis_sdk_tools.pytest_plugin" and a commented [tool.qgis-sdk] qgis-prefix; the generated webview.py honours QGIS_SDK_DEV_SERVER. Existing projects opt in by adding the addopts line (or passing -p qgis_sdk_tools.pytest_plugin). CliRuntime gains start_process; FakeCliRuntime records started processes in .started and the environments passed to run_process in .environments.
  • Curated services on PluginContext. layers, project, settings, styles, algorithms and workers are new optional fields with require_<name>() accessors; existing constructor calls are unaffected. HostServices.from_context(ctx) builds the web-view surface over the same instances, NetworkClient.transport is public, and qgis_sdk.adapters.qgis.native_plugin_context wires all of them inside QGIS. Projects generated by qgis-sdk new now carry a project_layers action and a build_context that uses it when a QgsApplication is running.
  • PluginContext is a class attribute. The runtime no longer calls plugin_class(context); it sets plugin_class.ctx = context and calls plugin_class(). Replace def __init__(self, ctx): self.ctx = ctx with a bare ctx: PluginContext annotation (and def __init__(self) if you still need one — self.ctx is already there). A constructor that keeps the ctx parameter fails start() with a QgisSdkPluginLifecycleError naming the change. AlgorithmContext and JobContext are unchanged: they are built fresh per invocation/attempt and still arrive through the constructor (decision-11, decision-13).
  • Declaration ids and titles are optional. @plugin, @action, @stream, @algorithm (removed again in 0.6.0), @job and @provider.algorithm derive a missing id= / title= from the decorated name (see “Ids and titles default from the name”) and the class and method decorators accept the bare form. Existing explicit declarations are unchanged; events= is now the only required keyword of @stream.
  • qgis-sdk new --web. The scaffold grows a questionnaire and the --web, --placement, --package-manager, --install/--no-install and --no-input flags; ScaffoldOptions gains web: WebOptions | None and the plan a web/ Vite app plus <plugin>/webview.py (see “Web UI”). Without --web the plan is unchanged. web and tests join the reserved package names. CliRuntime gains inp, interactive and run_process; FakeCliRuntime(input=, interactive=, run_process=) records spawned processes in .processes.
  • qgis-sdk check and qgis_sdk.check. New non-mutating project check with stable diagnostics (QGIS001, ARCH001, META00x, PROJECT001, CONFIG001, SYNTAX001); see “Project checks”. Commands now receive a qgis_sdk.cli.CliRuntime through ctx.obj; qgis_sdk.testing gains FakeCliRuntime.
  • CLI rename: the project generator is qgis-sdk new <directory> (python -m qgis_sdk new). qgis-sdk scaffold keeps working as a hidden, deprecated alias so existing scripts do not break; it will be removed in a later minor. The Python API (qgis_sdk.scaffold) is unchanged.