External Configuration Management
Introduction
This module contains classes and methods for doing inspection of external environments. The typical scenario when this is helpful is if you are creating an environment with mixed contexts - for example a Shotgun ‘My Tasks’ tool which lists different items from different projects and presents a list of available commands, apps or similar for each one of them. Building this would require Toolkit to load up the different configurations for each task and introspect them.
The following classes contains a collection of operations useful when you want to inspect and execute across projects and configurations.
The classes are aggressively cached and asynchronous, fetching data in the background and using QT signals to signal when it is available.
Configurations are bootstrapped in separate background processes, thereby ensuring complete stability of the runtime environment - no context switching or core changes take place.
Class ExternalConfigurationLoader
- class external_config.ExternalConfigurationLoader(interpreter, engine_name, plugin_id, base_config, bg_task_manager, parent)[source]
Class for loading configurations across contexts.
Signal Interface
- Signal configurations_loaded(project_id, configs):
Gets emitted configurations have been loaded for the given project. The parameters passed is the project id and a list of
ExternalConfiguration
instances. If errors occurred while loading configurations, the error property will be set to a tuple containing the error message and the traceback, in that order.- Signal configurations_changed():
Gets emitted whenever the class has detected a change to the state of shotgun which could invalidate any existing
ExternalConfiguration
instances. This can be emitted at startup or typically afterrefresh_shotgun_global_state()
has been called. Any implementation which cachesExternalConfiguration
instances can use this signal to invalidate their caches.
Initialize the class with the following parameters:
Note
The interpreter needs to support the VFX Platform, e.g be able to import
PySide
orPyside2
.- Parameters:
interpreter (str) – Path to Python interpreter to use.
engine_name (str) – Engine to run.
plugin_id (str) – Plugin id to use when executing external requests.
base_config (str) – Default configuration URI to use if nothing else is provided via Shotgun overrides.
bg_task_manager (
BackgroundTaskManager
) – Background task manager to use for any asynchronous work.parent (
QObject
) – QT parent object.
- refresh_shotgun_global_state()[source]
Requests an async refresh. If the State of Shotgun has changed in a way which may affect configurations, this will result in a
configurations_changed
signal being emitted.Examples of state changes which may affect configurations are any changes to related pipeline configuration, but also indirect changes such as a change to the list of software entities, since these can implicitly affect the list of commands associated with a project or entity.
- property engine_name
The name of the engine associated with this external configuration loader.
- property interpreter
The Python interpreter to when bootstrapping and loading external configurations.
- property plugin_id
The plugin id which will be used when executing external requests.
- property base_config_uri
Configuration URI string to be used when nothing is provided via Shotgun overrides.
- property software_hash
Hash string representing the state of the software entity in Shotgun or None if not yet determined.
- request_configurations(project_id)[source]
Requests a list of configuration objects for the given project.
Emits a
configurations_loaded
signal when the configurations have been loaded.Note
If this method is called multiple times in quick succession, only a single
configurations_loaded
signal will be emitted, belonging to the last request.- Parameters:
project_id (int) – Project to request configurations for.
- static connect(arg__1: PySide2.QtCore.QObject, arg__2: bytes, arg__3: Callable, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, arg__1: bytes, arg__2: Callable, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, arg__1: bytes, arg__2: PySide2.QtCore.QObject, arg__3: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, sender: PySide2.QtCore.QObject, signal: bytes, member: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static connect(sender: PySide2.QtCore.QObject, signal: PySide2.QtCore.QMetaMethod, receiver: PySide2.QtCore.QObject, method: PySide2.QtCore.QMetaMethod, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static connect(sender: PySide2.QtCore.QObject, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static disconnect(arg__1: PySide2.QtCore.QMetaObject.Connection) bool
- static disconnect(arg__1: PySide2.QtCore.QObject, arg__2: bytes, arg__3: Callable) bool
- static disconnect(self, arg__1: bytes, arg__2: Callable) bool
- static disconnect(self, receiver: PySide2.QtCore.QObject, member: Optional[bytes] = None) bool
- static disconnect(self, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes) bool
- static disconnect(sender: PySide2.QtCore.QObject, signal: PySide2.QtCore.QMetaMethod, receiver: PySide2.QtCore.QObject, member: PySide2.QtCore.QMetaMethod) bool
- static disconnect(sender: PySide2.QtCore.QObject, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes) bool
- findChildren(self, arg__1: type, arg__2: PySide2.QtCore.QRegExp) Iterable
- findChildren(self, arg__1: type, arg__2: PySide2.QtCore.QRegularExpression) Iterable
- findChildren(self, arg__1: type, arg__2: str = '') Iterable
- metaObject(self) PySide2.QtCore.QMetaObject
- parent(self) PySide2.QtCore.QObject
- sender(self) PySide2.QtCore.QObject
- startTimer(self, interval: int, timerType: PySide2.QtCore.Qt.TimerType = PySide2.QtCore.Qt.TimerType.CoarseTimer) int
- thread(self) PySide2.QtCore.QThread
Class ExternalConfiguration
- class external_config.ExternalConfiguration(parent, bg_task_manager, plugin_id, engine_name, interpreter, software_hash, pipeline_config_uri, status=1)[source]
Object wrapping an external pipeline configuration.
Signals
- Signal commands_loaded(project_id, config, commands):
Gets emitted after
request_commands()
has been called and once commands have been loaded for the configuration. The commands parameter contains a list ofExternalCommand
instances.- Signal commands_load_failed(project_id, config, reason):
Gets emitted after
request_commands()
has been called if command loading fails for some reason. The reason string parameter contains a message signfiying why the load failed.
Note
This class is constructed by
ExternalConfigurationLoader
. Do not construct objects by hand.Constructor parameters:
- Parameters:
parent (
QObject
) – QT parent object.bg_task_manager (
BackgroundTaskManager
) – Background task manager to use for any asynchronous work.plugin_id (str) – Associated bootstrap plugin id
engine_name (str) – Associated engine name
interpreter (str) – Associated Python interpreter
software_hash (str) – Hash representing the state of the Shotgun software entity
pipeline_config_uri (str) – Descriptor URI string for the config
status (int) – The status of the configuration. This is defined as a enum value provided by
ExternalConfiguration
.
- property plugin_id
The plugin id associated with the configuration.
- property engine_name
The engine name associated with the configuration.
- property interpreter
The Python interpreter to use when accessing this configuration
- property software_hash
A hash of the state of the software entity associated with this configuration.
- property is_primary
Returns
True
if this is the primary configuration,False
if not.
- property is_valid
Returns
True
if this configuration contains valid data that can be used in the current environment, andFalse
if the configuration is inaccessible for some reason.
- property status
The current status of the configuration. This will be returned as an enum value provided by
ExternalConfiguration
.
- property pipeline_configuration_id
The associated pipeline configuration id or
None
if not defined.
- property pipeline_configuration_name
The name of the associated pipeline configuration or
None
if not defined.
- property descriptor_uri
The descriptor URI associated with this pipeline configuration.
- property tracking_latest
Returns True if this configuration is tracking an external ‘latest version’. This means that we cannot rely on any caches - because a remote process may release a new “latest” version, we cannot know simply by computing a cache key or looking at a local state on disk whether a cached configuration is up to date or not. The only way to determine this is by actually fully resolve the configuration.
Note
External configurations with this property returning True will have their commands memoized; The first call to
request_commands()
will resolve the associated commands and subsequent requests will simply return that result. In order do perform a new evaluation of the list of associated commands, instantiate a new External Configuration instance.
- request_commands(project_id, entity_type, entity_id, link_entity_type, engine_fallback=None)[source]
Request commands for the given shotgun entity.
A
commands_loaded
signal will be emitted once the commands are available.- Parameters:
project_id (int) – Associated project id
entity_type (str) – Associated entity type
entity_id (int) – Associated entity id. If this is set to None, a best guess for a generic listing will be carried out.
link_entity_type (str) – Entity type that the item is linked to. This is typically provided for things such as task, versions or notes, where having different values it per linked type can be beneficial.
engine_fallback (str) – If the main engine isn’t available for the given entity id and project, request generate commands for the fallback engine specified. This can be useful in backwards compatibility scenarios.
- Raises:
RuntimeError if this configuration’s status does not allow for commands requests.
- static connect(arg__1: PySide2.QtCore.QObject, arg__2: bytes, arg__3: Callable, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, arg__1: bytes, arg__2: Callable, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, arg__1: bytes, arg__2: PySide2.QtCore.QObject, arg__3: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) bool
- static connect(self, sender: PySide2.QtCore.QObject, signal: bytes, member: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static connect(sender: PySide2.QtCore.QObject, signal: PySide2.QtCore.QMetaMethod, receiver: PySide2.QtCore.QObject, method: PySide2.QtCore.QMetaMethod, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static connect(sender: PySide2.QtCore.QObject, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes, type: PySide2.QtCore.Qt.ConnectionType = PySide2.QtCore.Qt.ConnectionType.AutoConnection) PySide2.QtCore.QMetaObject.Connection
- static disconnect(arg__1: PySide2.QtCore.QMetaObject.Connection) bool
- static disconnect(arg__1: PySide2.QtCore.QObject, arg__2: bytes, arg__3: Callable) bool
- static disconnect(self, arg__1: bytes, arg__2: Callable) bool
- static disconnect(self, receiver: PySide2.QtCore.QObject, member: Optional[bytes] = None) bool
- static disconnect(self, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes) bool
- static disconnect(sender: PySide2.QtCore.QObject, signal: PySide2.QtCore.QMetaMethod, receiver: PySide2.QtCore.QObject, member: PySide2.QtCore.QMetaMethod) bool
- static disconnect(sender: PySide2.QtCore.QObject, signal: bytes, receiver: PySide2.QtCore.QObject, member: bytes) bool
- findChildren(self, arg__1: type, arg__2: PySide2.QtCore.QRegExp) Iterable
- findChildren(self, arg__1: type, arg__2: PySide2.QtCore.QRegularExpression) Iterable
- findChildren(self, arg__1: type, arg__2: str = '') Iterable
- metaObject(self) PySide2.QtCore.QMetaObject
- parent(self) PySide2.QtCore.QObject
- sender(self) PySide2.QtCore.QObject
- startTimer(self, interval: int, timerType: PySide2.QtCore.Qt.TimerType = PySide2.QtCore.Qt.TimerType.CoarseTimer) int
- thread(self) PySide2.QtCore.QThread
Class ExternalCommand
- class external_config.ExternalCommand(callback_name, display_name, tooltip, group, is_group_default, plugin_id, interpreter, engine_name, descriptor_uri, pipeline_config_id, entity_type, entity_id, pipeline_config_name, sg_deny_permissions, sg_supports_multiple_selection, icon)[source]
Represents an external Toolkit command (e.g. menu option).
These objects are emitted by
ExternalConfiguration
and are independent, decoupled, light weight objects that can be serialized and brought back easily.A command is executed via its
execute()
method, which will launch it in the given engine.Note
This class is constructed by
ExternalConfigurationLoader
. Do not construct objects by hand.- Parameters:
callback_name (str) – Name of the associated Toolkit command callback
display_name (str) – Display name for command
tooltip (str) – Tooltip
group (str) – Group that this command belongs to
is_group_default (bool) – Indicates that this is a group default
plugin_id (str) – Plugin id
interpreter (str) – Associated Python interpreter
engine_name (str) – Engine name to execute command in
descriptor_uri (str) – Associated descriptor URI
pipeline_config_id (int) – Associated pipeline configuration id
entity_type (str) – Associated entity type
entity_id (int) – Associated entity id
pipeline_config_name (str) – Associated pipeline configuration name
sg_deny_permissions (list) – (Shotgun specific) List of permission groups to exclude this action from.
sg_supports_multiple_selection (bool) – (Shotgun specific) Action supports multiple selection.
icon (str) – The path to a square png icon file representing this item
- classmethod is_compatible(data)[source]
Determines if the given data is compatible.
- Parameters:
data (dict) – Serialized data
- Returns:
True if the given data can be loaded, False if not.
- classmethod is_valid_data(data)[source]
Tests whether key components of the data contained in the cache are still valid. This helps protect against file paths that might have been cached that no longer exist.
- Parameters:
data (dict) – Serialized data
- Returns:
True if the given data passes validation, False if not.
- classmethod deserialize(data)[source]
Creates a
ExternalCommand
instance given some serialized data.- Parameters:
data (str) – Data created by
serialize()
- Returns:
External Command instance.
- Return type:
- Raises:
RuntimeError
if data is not valid
- serialize()[source]
Serializes the current object into a string.
For use with
deserialize()
.- Returns:
String representing the current instance.
- Return type:
- property pipeline_configuration_name
The name of the Shotgun pipeline configuration this command is associated with, or
None
if no association exists.
- property system_name
The system name for the command
- property engine_name
The name of the engine associated with the command
- property display_name
Display name, suitable for display in a menu.
- property icon
The path to a square png icon file representing this item
- property group
Group command belongs to or None if not defined.
This is used in conjunction with the
group()
property and is a hint to engines how commands should be grouped together.Engines which implement support for grouping will group commands which share the same
group()
name into a group of associated items (typically as a submenu). Thegroup_default()
boolean property is used to indicate which item in the group should be considered the default one to represent the group as a whole.
- property is_group_default
True if this command is a default action for a group.
This is used in conjunction with the
group()
property and is a hint to engines how commands should be grouped together.Engines which implement support for grouping will group commands which share the same
group()
name into a group of associated items (typically as a submenu). Thegroup_default()
boolean property is used to indicate which item in the group should be considered the default one to represent the group as a whole.
- property excluded_permission_groups_hint
Legacy option used by some older Shotgun toolkit apps. Apps may hint a list of permission groups for which the app command should not be displayed.
Returns a list of Shotgun permission groups (as strings) where this command is not appropriate.
- property support_shotgun_multiple_selection
Legacy flag indicated by some older Toolkit apps, indicating that the app can accept a list of entity ids to operate on rather than a single item.
- property tooltip
Associated help text tooltip.
- property interpreter
The Python interpreter path to use when executing the command.
- execute(pre_cache=False)[source]
Executes the external command in a separate process.
Note
The process will be launched in an synchronous way. It is recommended that this command is executed in a worker thread:
# execute external command in a thread to not block # main thread execution worker = threading.Thread(target=action.execute) # if the python environment shuts down, no need # to wait for this thread worker.daemon = True # launch external process worker.start()
- Parameters:
pre_cache (bool) – If set to True, starting up the command will also include a full caching of all necessary dependencies for all contexts and engines. If set to False, caching will only be carried as needed in order to run the given command. This is an advanced setting that can be useful to set to true when launching older engines which don’t launch via a bootstrap process. In that case, the engine simply assumes that all necessary app dependencies already exists in the bundle cache search path and without a pre-cache, apps may not initialize correctly.
- Raises:
RuntimeError
on execution failure.- Returns:
Output from execution session.
- execute_on_multiple_entities(pre_cache=False, entity_ids=None)[source]
Executes the external command in a separate process. This method provides support for executing commands that support being run on multiple entities as part of a single execution.
- Parameters:
pre_cache (bool) – If set to True, starting up the command will also include a full caching of all necessary dependencies for all contexts and engines. If set to False, caching will only be carried as needed in order to run the given command. This is an advanced setting that can be useful to set to true when launching older engines which don’t launch via a bootstrap process. In that case, the engine simply assumes that all necessary app dependencies already exists in the bundle cache search path and without a pre-cache, apps may not initialize correctly.
entity_ids (list) – A list of entity ids to use when executing the command. This is only required when running legacy commands that support being run on multiple entities at the same time. If not given, a list will be built on the fly containing only the entity id associated with this command.
- Raises:
RuntimeError
on execution failure.- Returns:
Output from execution session.