Migrating to OctoPrint 2.0.0¶
With OctoPrint 2.0.0 quite a number of compatibility layers in place for most of the past decade are finally getting removed, causing potential breakage for existing plugins still relying on these compatibility layers after having ignored the related deprecation warnings for years.
It’s time to finally migrate, and this guide is in place to show you how to quickly get your plugin up and running under OctoPrint 2.0.0 again as all but 1 of the removed deprecated endpoints and functions have had replacements available for a long time already!
Note
This looks like an incredibly long list. But please don’t get discouraged by this. Most plugins won’t have to do anything but maybe one or two points, some not even anything at all.
This migration guide lists all changes in OctoPrint 2.0.0 that might require changes in any plugin (or client) implementations. Whether your plugin is affected by any of them relies heavily on the implementation and complexity of your plugin.
However, even if you are not affected by any of the necessary changes, please take note of the section on migrating your plugin to the use of pyproject.toml and also the section on upcoming removals that already have active deprecation warnings.
Server side¶
Access control¶
Changes in octoprint.access.users.*¶
Various long deprecated (and replaced) methods have been removed from octoprint.access.users.UserManager, octoprint.access.users.FilebasedUserManager, octoprint.access.users.User and octoprint.access.users.SessionUser. If your code utilizes any of them, you’ll need to migrate.
What follows is a list of all methods and their corresponding replacements:
octoprint.access.users.UserManager:checkPassword->check_passwordaddUser->add_userchangeUserActivation->change_user_activationchangeUserPassword->change_user_passwordgetUserSetting->get_user_settinggetAllUserSettings->get_all_user_settingschangeUserSetting->change_user_settingchangeUserSettings->change_user_settingsremoveUser->remove_userfindUser->find_usergetAllUsers->get_all_usershasBeenCustomized->has_been_customizedchangeUserRoles->change_user_permissionsaddRolesToUser->add_permissions_to_userremoveRolesFromUser->remove_permissions_from_user
octoprint.access.users.FilebasedUserManager:generateApiKey->generate_api_keydeleteApiKey->delete_api_keyaddUser->add_userchangeUserActivation->change_user_activationchangeUserPassword->change_user_passwordgetUserSetting->get_user_settinggetAllUserSettings->get_all_user_settingschangeUserSetting->change_user_settingchangeUserSettings->change_user_settingsremoveUser->remove_userfindUser->find_usergetAllUsers->get_all_usershasBeenCustomized->has_been_customized
octoprint.access.users.User:asDict->as_dictis_admin,is_user,roles-> check specific permissions instead, e.g.:from octoprint.access.permissions import Permissions # instead of user.is_admin: is_admin = user.has_permission(Permissions.ADMIN) # preferred! is_admin = "admin" in user.groups # instead of user.is_user: is_user = not user.is_anonymous # preferred! is_user = "user" in user.groups
octoprint.access.users.SessionUserget_session->session
Removed octoprint.users¶
octoprint.users has long been deprecated and has finally been removed in 2.0.0. Change your imports to octoprint.access.users.
Removed octoprint.server.admin_permission & octoprint.server.user_permission¶
Both of these permission helpers have long been deprecated and have finally been removed in 2.0.0. Use individual and specific permissions instead. Easy drop-in replacements follow:
from octoprint.access import groups
admin_permission = groups.GroupPermission(groups.ADMIN_GROUP)
user_permission = groups.GroupPermission(groups.USER_GROUP)
However, it is strongly recommended to think whether some more granular (and possibly custom) permissions aren’t better suited for your specific usecase!
File storage, printable files¶
Changed value of octoprint.filemanager.FileDestinations.SDCARD¶
The value of FileDestinations.SDCARD has changed from printer to sdcard. Any plugins that compared it against the hardcoded string will fail the comparison. Switch your code to using FileDestinations.PRINTER for all required checks! Example:
from octoprint.storage import FileDestinations
if storage == FileDestinations.PRINTER: # preferred!
# do something
if storage == FileDestinations.SDCARD:
# do something
Dropped event type gcode for UpdatedFiles event¶
The UpdatedFiles event generated inside the storage subsystem is no longer generated for the file type gcode but only for the file type printables now.
If you still rely on UpdatedFiles to be fired with type: gcode, you need
to switch over to type: printables now.
Plugin system¶
Endpoints provided through the BlueprintPlugin mixin do now automatically fall under OctoPrint’s CSRF protection¶
As of OctoPrint 2.0.0 and announced with the release of OctoPrint 1.8.3, endpoints provided through a BlueprintPlugin mixin do now automatically fall under OctoPrint’s CSRF protection.
If this breaks your plugin, you can exempt individual endpoints through the @octoprint.plugin.BlueprintPlugin.csrf_exempt decorator:
class MyPlugin(octoprint.plugin.BlueprintPlugin):
@octoprint.plugin.BlueprintPlugin.route("/hello_world", methods=["GET"])
def hello_world(self):
# This is a GET request and thus not subject to CSRF protection
return "Hello world!"
@octoprint.plugin.BlueprintPlugin.route("/hello_you", methods=["POST"])
def hello_you(self):
# This is a POST request and thus subject to CSRF protection. It is not exempt.
return "Hello you!"
@octoprint.plugin.BlueprintPlugin.route("/hello_me", methods=["POST"])
@octoprint.plugin.BlueprintPlugin.csrf_exempt()
def hello_me(self):
# This is a POST request and thus subject to CSRF protection, but this one is exempt.
return "Hello me!"
def is_blueprint_csrf_protected(self):
return True
octoprint.plugin.PluginSettings.get_plugin_data_folder removed¶
The long-deprecated octoprint.plugin.PluginSettings.get_plugin_data_folder has finally been removed in favor of its established replacement octoprint.plugin.OctoPrintPlugin.get_plugin_data_folder.
In practice for plugins that means replacing any calls to self._settings.get_plugin_data_folder with self.get_plugin_data_folder. Note that if the only reason for your plugin to implement the SettingsPlugin mixin was to be able to access your plugin’s data folder, you can then also remove that mixin from your plugin.
Printer interaction¶
Internal attributes of Printer class renamed or removed¶
Some internal attributes of the octoprint.printer.Printer class (injected as self._printer into plugin implementations) have been renamed or removed. Plugins that accessed the following (private) attributes will need to update the names. Please note that these are not drop-in replacements!
Attention
Your plugin should not use private & undocumented properties on OctoPrint’s internal classes. However looking at the plugins on the official plugin repository it’s clear that quite a number of plugins utilize these directly.
This is supposed to be avoided, but clearly there’s a reason why so many plugin authors have decided to rely on undocumented implementation details.
If this affects you, then please open a feature request on OctoPrint’s repository and tell us what exactly you need that’s currently missing from the plugin interface and documented internal APIs so that ideally we can make things officially supported and avoid issues like this in the future!
The affected names are:
_currentZ->_last_z_fileManager->_file_manager_printerProfileManager->_printer_profile_manager_selectedFile->_selected_job_comm-> still available, however with a deprecation warning and only if the current connection happens to be provided by the bundled serial connector plugin; see here for an alternative access method
Printer.get_transport deprecated¶
get_transport has been deprecated, and the compatibility layer in place is only functional if the current printer connection is provided by the bundled serial connector plugin.
This compatibility layer is planned to get removed in a future version, so if your plugin still relies on self._printer, for now refactor it to instead check for the serial connector yourself and then fetch the _comm and its _serial object yourself, with a lot of error checking to protect against internal changes (these are private properties shown by the _ prefix - they are not part of the official plugin API!):
if self._printer.connection is None or self._connection.connector != "serial":
return
if hasattr(self._connection, "_comm"):
# this gets you what used to be self._printer._comm...
comm = self._connection._comm
if hasattr(comm, "_serial"):
# ... and this what used to be returned by self._printer.get_transport()
serial = comm._serial
Plugins that need access like this should please get in touch in the shape of a feature request so we can figure out how to achieve what they so far have been doing by utilizing this method in an officially supported and documented way that does not rely on implementation details!
Format of terminal log lines changed¶
Terminal log lines as generated by the serial connection no longer have the prefixes Recv: and Send: but rather <<< and >>>.
Any consumers of these logs must update their parsers.
The terminal filters have already been updated accordingly.
octoprint.printer.profile.BedTypes removed¶
The long deprecated octoprint.printer.profile.BedTypes type has been removed. Its drop-in replacement is the more aptly named octoprint.printer.profile.BedFormFactor.
Server¶
(sec-plugins-octo_2_0_0-server-server-validator)
octoprint.server.util.flask.(admin|user)_validator removed¶
Both octoprint.server.util.flask.admin_validator and octoprint.server.util.flask.user_validator have been removed in favor of octoprint.server.util.flask.permissions_validator
Settings¶
The serial.* block has moved¶
The serial block in the settings schema has moved to plugins.serial_connector as it’s now managed by that bundled plugin.
If you are accessing any serial related settings in your plugin, you’ll need to adapt your accessing code. In most cases you can just replace all settings paths referring to serial.* with plugins.serial_connector.*, with the following exceptions:
serial.port->printerConnection.preferred.parameters.portserial.baudrate->printerConnection.preferred.parameters.baudrateserial.autoconnect->printerConnection.autoconnectserial.autorefresh->printerConnection.autorefreshserial.autorefreshInterval->printerConnection.autorefreshIntervalserial.notifySuppressedCommands->feature.notifySuppressedCommandsserial.alwaysSendChecksum,serial.neverSendChecksum->plugins.serial_connector.sendChecksum, set toalwaysorneverserial.disconnectOnErrors,serial.ignoreErrorsFromFirmware->plugins.serial_connector.errorHandling, set todisconnectorignoreserial.blacklistedPorts->plugins.serial_connector.blacklistedPorts(see also below)serial.blacklistedBaudrates->plugins.serial_connector.blacklistedBaudrates(see also below)
Info
A compatibility layer is in place performing these mappings for you, however please migrate your plugin ASAP if it does access any of these settings to not be hit by the next removal cycle of deprecated features!
More inclusive language with regards to “blacklist” and “whitelist”¶
The following path names containing the words “blacklist” or “whitelist” have been moved to the more inclusive phrasing “blocklist” and “allowlist” and calling code should adapt:
feature.autoUppercaseBlacklist->feature.autoUppercaseBlocklistserver.pluginBlacklist->server.pluginBlocklistserial.blacklistedPorts->plugins.serial_connector.blocklistedPorts(see also above)serial.blacklistedBaudrates->plugins.serial_connector.blocklistedBaudrates(see also above)
Info
A compatibility layer is in place performing these mappings for you, however please migrate your plugin ASAP if it does access any of these settings to not be hit by the next removal cycle of deprecated features!
octoprint.settings.SettingsManager._config removed¶
The long deprecated octoprint.settings.SettingsManager._config field has been removed. If you need read access to its old value, use the config property instead.
Write access should be avoided at all costs, but if absolutely necessary can be achieved through _map.topmap.
Util¶
There have been changes to the following long-deprecated methods from octoprint.util:
octoprint.util.bom_aware_openremoved, use the-sigsuffixed encoding to handle BOM automatically, e.g.with open(filename, encoding="utf-8-sig", mode="r") as f: # do somethingoctoprint.util.dict_cleanremoved, useoctoprint.util.dict_sanitizeinsteadoctoprint.util.to_strremoved, useoctoprint.util.to_bytesinsteadoctoprint.util.to_native_strremoved, useoctoprint.util.to_unicodeinsteadoctoprint.util.commandline.clean_ansino longer acceptsbytesas input, convert tostrbefore callingoctoprint.util.json.dumpremoved, useoctoprint.util.json.dumpsinstead
Client side¶
Viewmodels¶
Removed usersViewModel¶
The usersViewModel has long been deprecated and was only a redirect to accessViewModel.users. Use that instead as a direct drop-in replacement.
Removed support for deprecated method calling signature on FilesViewModel.requestData¶
Calling FilesViewModel.requestData with a parameter list of (focus, switchToPath, force) is no longer supported. Instead use the single params parameter:
const params = {
focus: undefined,
switchToPath: undefined,
force: false
}
self.filesViewModel.requestData(params);
Changed signature on FilesViewModel.fromResponse¶
FilesViewModel.fromResponse now expects being called with the parameters (response, params), mirroring the changes to requestData.
Removed support for deprecated method calling signature on SettingsViewModel.requestData¶
Calling SettingsViewModel.requestData with a callback parameter is no longer supported.
Instead, use the returned promise:
self.settingsViewModel.requestData()
.done((response) => {
// do something
});
onWizardTabChange removed¶
This has long been replaced by onBeforeWizardTabChange, so if your plugin still relies on the old name, please just switch to the new.
JS Client¶
Removed clients for removed API endpoints¶
The following JS Client components have been removed, with established replacements documented next to them:
OctoPrintClient.logs->OctoPrintClient.plugins.loggingOctoPrintClient.users->OctoPrintClient.access.users
Removed support for deprecated method calling signature on OctoPrintClient.getRequestHeaders¶
Calling OctoPrintClient.getRequestHeaders with additional headers as the first argument
is no longer supported, instead callers need to add additional headers via the additional
parameter. Example:
const headers = OctoPrintClient.getRequestHeaders(
"POST",
{"Some-Header": "Some Value"}
)
Removed OctoPrintClient.deprecatedMethod¶
If your plugin was using this, use OctoPrintClient.deprecated instead.
Changed signature on OctoPrintClient.deprecatedVariable¶
If your plugin was using this, make sure to adjust the calling parameters to the
new signature. Refer to the documentation of OctoPrintClient.deprecatedVariable for details.
API¶
Global API Key¶
The Global API Key has been deprecated for a while, with 2.0.0 it is no longer automatically generated at startup and may thus be empty! It will be removed entirely in 2.1.0.
Instead of utilizing this key to talk to OctoPrint’s API endpoints from plugin code, plugins
should instead use self.plugin_apikey. Example:
import octoprint.plugin
import requests
class MyPlugin(octoprint.plugin.StartupPlugin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._port = 5000
def on_startup(self, host, port, *args, **kwargs):
self._port = port
def fetch_api_version(self, **kwargs):
url = f"https://localhost:{self._port}/api/version"
headers = {
"X-Api-Key": self.plugin_apikey
}
return requests.get(url, headers=headers, timeout=5)
/api/logs/*, /api/users/* and /api/plugin/pluginmanager removed¶
The following long deprecated API endpoints have been removed, with their established replacements shown next to them:
/api/logs/*->/plugin/logging/logs/*/api/users/*->/api/access/users/*/api/plugin/pluginmanager->/plugin/pluginmanager/(plugins|orphans|repository)
Clients still relying on the old endpoints need to switch to the new ones.
admin and user fields dropped on user responses on API¶
Any API responses related to users no longer contain the admin and user fields. You can still determine these from the returned groups.
Project organisation¶
Dependencies¶
The netifaces and passlib libraries are no longer part of the dependencies of OctoPrint. Any plugins that import them without listing them as additional requirements will no longer be usable. If your plugin relies on functionality provided by either of these third party libraries, make sure to also make them part of your plugin’s requirements by explicitly declaring them in setup.py or pyproject.toml.
pyproject.toml and build isolation¶
Now is as good a time as any to also migrate your plugin to use pyproject.toml and build isolation, should you still be on the old setup.py based build approach.
Prepare for upcoming removals too!¶
While you are it, please also take care of some upcoming removals that already have deprecation warnings going on. Refer to the list of current deprecations!