Skip to content

feat: [SG-43418] Unified context locking for Publisher dialog#219

Draft
chenm1adsk wants to merge 1 commit into
masterfrom
ticket/SG-43418-improve-context-handling
Draft

feat: [SG-43418] Unified context locking for Publisher dialog#219
chenm1adsk wants to merge 1 commit into
masterfrom
ticket/SG-43418-improve-context-handling

Conversation

@chenm1adsk

Copy link
Copy Markdown
Contributor

Current state of tk-multi-publish2

  1. No native context widget locking - locking was enforced at the DCC engine level using templates, not within tk-multi-publish2 itself.

  2. No context isolation between dialogs - all dialogs fell back to the process-wide engine context singleton, so engine.change_context() called while a dialog was open could silently mutate the context of items in already-open dialogs.

  3. No way for callers to pass a target context or seed properties to the dialog without relying on process-wide env vars or private APIs.

Now handled natively in tk-multi-publish2

These are addressed by supporting two scenarios based on whether the caller's context matches the engine's own context:

Scenario A - Engine already in task context** (e.g. Maya opened from
a task workfile, context == bundle.context): the launch context is
snapshotted onto root_item at dialog init time, isolating the item tree
from concurrent engine.change_context() calls. After collection, items
with a fully resolved task + entity have their context widget locked
(read-only).

Scenario B - Caller passes a context different from the engine**
(e.g. Loader in a project-level tk-desktop engine passing a task
context, context != bundle.context): the context is stored as
_pre_fill_context and applied to top-level items after collection so
the context widget is pre-filled. The widget remains editable since the
supplied context is a suggestion. Pre-fill must run after collection to
avoid breaking plugin loading via pick_environment.

show_dialog() and AppDialog.init now accept context= and root_item_properties= keyword arguments so callers can pass seed properties (e.g. am_revision_id) directly.

Current state of tk-multi-publish2
----

1. No native context widget locking - locking was enforced at the DCC
   engine level using templates, not within tk-multi-publish2 itself.

2. No context isolation between dialogs - all dialogs fell back to the
   process-wide engine context singleton, so engine.change_context()
   called while a dialog was open could silently mutate the context of
   items in already-open dialogs.

3. No way for callers to pass a target context or seed properties to
   the dialog without relying on process-wide env vars or private APIs.

Now handled natively in tk-multi-publish2
----
These are addressed by supporting two scenarios based on whether
the caller's context matches the engine's own context:

**Scenario A** - Engine already in task context** (e.g. Maya opened from
  a task workfile, context == bundle.context): the launch context is
  snapshotted onto root_item at dialog init time, isolating the item tree
  from concurrent engine.change_context() calls. After collection, items
  with a fully resolved task + entity have their context widget locked
  (read-only).

**Scenario B** - Caller passes a context different from the engine**
  (e.g. Loader in a project-level tk-desktop engine passing a task
  context, context != bundle.context): the context is stored as
  _pre_fill_context and applied to top-level items after collection so
  the context widget is pre-filled. The widget remains editable since the
  supplied context is a suggestion. Pre-fill must run after collection to
  avoid breaking plugin loading via pick_environment.

show_dialog() and AppDialog.__init__ now accept context= and
root_item_properties= keyword arguments so callers can pass seed
properties (e.g. am_revision_id) directly.
@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 31.25000% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.75%. Comparing base (8be9070) to head (f28aed3).

Files with missing lines Patch % Lines
python/tk_multi_publish2/api/manager.py 40.90% 13 Missing ⚠️
python/tk_multi_publish2/dialog.py 0.00% 7 Missing ⚠️
python/tk_multi_publish2/__init__.py 33.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #219      +/-   ##
==========================================
- Coverage   40.81%   40.75%   -0.06%     
==========================================
  Files          63       63              
  Lines        5109     5135      +26     
==========================================
+ Hits         2085     2093       +8     
- Misses       3024     3042      +18     
Flag Coverage Δ
Linux 40.75% <31.25%> (-0.06%) ⬇️
Python-3.10 40.75% <31.25%> (-0.06%) ⬇️
Python-3.11 40.75% <31.25%> (-0.06%) ⬇️
Python-3.13 40.75% <31.25%> (-0.06%) ⬇️
Python-3.9 40.76% <31.25%> (-0.06%) ⬇️
Windows 40.75% <31.25%> (-0.06%) ⬇️
macOS 40.75% <31.25%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@chenm1adsk chenm1adsk marked this pull request as draft June 8, 2026 20:07
@chenm1adsk chenm1adsk requested a review from Copilot June 8, 2026 20:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class, dialog-scoped context handling to tk-multi-publish2 so the Publisher UI can (a) isolate its item tree from concurrent engine.change_context() calls and (b) optionally pre-fill a caller-supplied target context without relying on process-wide context mutation.

Changes:

  • Extend show_dialog() and AppDialog to accept context= and root_item_properties= and forward them into PublishManager.
  • Update PublishManager to support context snapshotting vs. post-collection pre-fill, and add a gating step to lock context editing when context is fully resolved.
  • Add a Desktop-specific collector hook to block publishing DCC-native files from Desktop workflows.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 12 comments.

File Description
python/tk_multi_publish2/dialog.py Passes context/root seed properties into the manager and applies pre-fill + lock-gating after collection; includes doc/comment updates.
python/tk_multi_publish2/api/manager.py Adds context snapshot/pre-fill support plus context-lock gating APIs; adjusts initialization and introduces new post-collection helpers.
python/tk_multi_publish2/__init__.py Extends show_dialog() API to accept and forward context and root_item_properties.
hooks/flowam/collector_desktop.py New hook to block DCC file types from Desktop publishing and provide user-facing guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

)
return None

return self._collect_file(parent_item, path)
Comment on lines +42 to +43
file_info = self.parent.util.get_file_path_components(path)
extension = file_info["extension"]

if extension in dcc_extensions:
# Get the file type display name
file_type = "Unknown"
Comment on lines +285 to +287
# create a publish manager - snapshot the launch context onto the root
# item so that this dialog is isolated from concurrent engine.change_context() calls.
# An explicit context takes priority over the current engine context.
Comment on lines +57 to +59
:param context: Optional sgtk.Context to pin this dialog to. When set,
overrides the current engine context for this dialog's item tree.
Useful for callers that cannot call engine.change_context() first.
Comment on lines +66 to +69
:param context: Optional sgtk.Context to snapshot onto the root item.
When set, item context resolution stops at the root and never falls
back to the process-wide engine singleton - isolating this dialog
from concurrent context changes.
Comment on lines +430 to +433
if self._pre_fill_context:
for item in self._tree.root_item.children:
if item._context is None:
item._context = self._pre_fill_context
Comment on lines 411 to +416
@property
def context(self):
"""Returns the execution context of the manager."""
return self._bundle.context

@property
Comment on lines +436 to +440
"""Lock context widget for items whose context is fully resolved.

Only applied when engine already in task context. When the caller
passed a different context, the context is a suggestion and the
user should still be able to change it.
Comment on lines +421 to +447
def apply_pre_fill_context(self):
"""Apply pre-fill context to top-level items after collection.

Only applied when the caller passed a context that differs from
bundle.context (e.g. Loader passing a Task context into a
project-level engine). When the engine is already in task context,
items inherit it via the fallback chain and no pre-fill is needed.
Skips items where the collector already set an explicit context.
"""
if self._pre_fill_context:
for item in self._tree.root_item.children:
if item._context is None:
item._context = self._pre_fill_context

def apply_context_lock_gate(self):
"""Lock context widget for items whose context is fully resolved.

Only applied when engine already in task context. When the caller
passed a different context, the context is a suggestion and the
user should still be able to change it.
"""
if self._pre_fill_context is not None:
return
for item in self._tree.root_item.children:
ctx = item.context
if ctx and ctx.entity and ctx.task:
item.context_change_allowed = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants