Install extensions from the command line using Slicer 5.2.2

Hi,
can Slicer extensions be installed from the command line? If yes, where can I find the related documentation?

Thanks.

In the past I’ve used this:

to run this script:

But you can also use this newer code:
https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#download-and-install-extension

OK, thanks Steve. Will give it a try and report back as time permits.

So, when launching the shell command (using Slicer 5.2.2 on an Ubuntu 22.04 machine), e.g.

slicer_ext="CurveMaker"

export EXTENSION_TO_INSTALL=${slicer_ext}

./Slicer \
  --no-splash \
  --no-main-window \
  --python-script "/<my_path>/install_slicer_extension.py"

where the install_slicer_extension.py script is esentially what you kindly posted in https://github.com/pieper/SlicerDockers/blob/master/slicer-plus/install-slicer-extension.py, I get the following error:

installing CurveMaker
Traceback (most recent call last):
  File "<string>", line 5, in <module>
  File "<string>", line 28, in <module>
  File "<string>", line 17, in main
AttributeError: qSlicerExtensionsManagerModel has no attribute named 'retrieveExtensionMetadataByName'

the command hangs, and the installation does not take place.

So maybe something changed from the version you used at the time (5.0.2 according to the commit message) and 5.2.2?

Starting with Slicer 5.4, a dedicated API was introduced to streamline the programmatic installation of extensions.

See https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#download-and-install-extension

Steve already pointed to that possibility for Slicer 5.4; I’m using 5.2.2, though.

See BUG: fix/doc DMRIInstall (#6594) · Slicer/Slicer@537281b · GitHub

Hitting the very same error reported earlier even when modifying the script according to it.

With Slicer >= 5.2, consider using the following script:

import os


extensionName = os.environ['EXTENSION_TO_INSTALL']
em = slicer.app.extensionsManagerModel()
if not em.isExtensionInstalled(extensionName):
    em.interactive = False  # prevent display of popups
    em.updateExtensionsMetadataFromServer(True, True)  # update extension metadata from server now
    installDependencies = True
    if not em.downloadAndInstallExtensionByName(extensionName, installDependencies, True):
        raise ValueError(f"Failed to install {extensionName} extension")

Assuming you saved it as /tmp/install_slicer_extension.py, you may run it using:

$ EXTENSION_TO_INSTALL=Sandbox \
~/Downloads/Slicer-5.2.2-linux-amd64/Slicer \
  --exit-after-startup \
  --no-main-window \
  --disable-modules \
  --python-script /tmp/install_slicer_extension.py

Retrieving extension metadata for Sandbox extension
Retrieving Sandbox extension files (extensionId: 63f5ca688939577d9867ba35)
Downloading Sandbox extension (item_id: 63f5ca688939577d9867ba35, file_id: 64c8c82516826926710d5a97)
Installed extension Sandbox (63f5ca688939577d9867ba35) revision e163d61

And here is an improved version allowing to install extensions in Slicer 5.2.2 while passing extension names as regular arguments:

import sys


def install_exttension(extensionName, installDependencies=True):
    print(f"\nInstalling extension {extensionName}")
    em = slicer.app.extensionsManagerModel()
    if em.isExtensionInstalled(extensionName):
        print(f"Extension {extensionName} already installed")
        return

    em.interactive = False  # prevent display of popups
    em.updateExtensionsMetadataFromServer(True, True)  # update extension metadata from server now

    if not em.downloadAndInstallExtensionByName(extensionName, installDependencies, True):
        raise ValueError(f"Failed to install {extensionName} extension")


if __name__ == "__main__":
    for extensionName in sys.argv[1:]:
        install_exttension(extensionName)

For future reference, to install extension in Slicer 5.4, there is a dedicated API to do so. See here

Then, to install extensions:

$ ads/Slicer-5.2.2-linux-amd64/Slicer \
  --exit-after-startup \
  --no-main-window \
  --disable-modules \
  --python-script /tmp/install_slicer_extension.py \
  Sandbox \
  SlicerHeart \
  SlicerDMRI

and example of output:

Installing extension Sandbox
Retrieving extension metadata for Sandbox extension
Retrieving Sandbox extension files (extensionId: 63f5ca688939577d9867ba35)
Downloading Sandbox extension (item_id: 63f5ca688939577d9867ba35, file_id: 64c8c82516826926710d5a97)
Installed extension Sandbox (63f5ca688939577d9867ba35) revision e163d61

Installing extension SlicerHeart
Retrieving extension metadata for SlicerHeart extension
Retrieving SlicerHeart extension files (extensionId: 63f5f3f08939577d9867dbc7)
Downloading SlicerHeart extension (item_id: 63f5f3f08939577d9867dbc7, file_id: 64de321206a93d6cff35a4c1)
"The following extensions are required by SlicerHeart extension therefore they will be installed now: SlicerIGT, SlicerIGSIO"
Retrieving extension metadata for SlicerIGT extension
Retrieving SlicerIGT extension files (extensionId: 63f5f2d78939577d9867da34)
Downloading SlicerIGT extension (item_id: 63f5f2d78939577d9867da34, file_id: 64aa9a94b81c954f339bfef6)
Retrieving extension metadata for SlicerIGSIO extension
Retrieving SlicerIGSIO extension files (extensionId: 63f5da488939577d9867c528)
Downloading SlicerIGSIO extension (item_id: 63f5da488939577d9867c528, file_id: 64c0f2c6c0e19dd3b30f7352)
Installed extension SlicerHeart (63f5f3f08939577d9867dbc7) revision 09e440d
Installed extension SlicerIGT (63f5f2d78939577d9867da34) revision 245fa92
Installed extension SlicerIGSIO (63f5da488939577d9867c528) revision b6328fd

Installing extension SlicerDMRI
Retrieving extension metadata for SlicerDMRI extension
Retrieving SlicerDMRI extension files (extensionId: 63fb32ce8939577d9869e2b2)
Downloading SlicerDMRI extension (item_id: 63fb32ce8939577d9869e2b2, file_id: 64ccc3ed16826926710f2500)
"The following extensions are required by SlicerDMRI extension therefore they will be installed now: UKFTractography"
Retrieving extension metadata for UKFTractography extension
Retrieving UKFTractography extension files (extensionId: 63f5eae38939577d9867d2b3)
Downloading UKFTractography extension (item_id: 63f5eae38939577d9867d2b3, file_id: 63f5eae38939577d9867d2ba)
Installed extension SlicerDMRI (63fb32ce8939577d9869e2b2) revision aad4331
Installed extension UKFTractography (63f5eae38939577d9867d2b3) revision fcf83e2

OK, after some more work, got it working: looks like I had still carried over the statement to call retrieveExtensionMetadataByName in https://github.com/pieper/SlicerDockers/blob/master/slicer-plus/install-slicer-extension.py#L7C3-L7C77, so the instructions in Install extensions from the command line using Slicer 5.2.2 - #10 by jcfr worked.

Thanks for the effort @jcfr.