Submits a movie file to ShotGrid for review. An entry will be diff --git a/hooks/tk-multi-publish2/icons/flame.png b/hooks/tk-multi-publish2/icons/flame.png index a13a565..b96a434 100755 Binary files a/hooks/tk-multi-publish2/icons/flame.png and b/hooks/tk-multi-publish2/icons/flame.png differ diff --git a/info.yml b/info.yml index 685e272..fd0e7f7 100755 --- a/info.yml +++ b/info.yml @@ -21,9 +21,9 @@ configuration: launch_builtin_plugins: type: list - description: Comma-separated list of tk-maya plugins to load when launching Maya. Use + description: Comma-separated list of tk-nuke plugins to load when launching Nuke. Use of this feature disables the classic mechanism for bootstrapping Toolkit - when Maya is launched. + when Nuke is launched. allows_empty: True default_value: [] values: @@ -148,7 +148,7 @@ configuration: type: int description: "Specify the minimum Application major version that will prompt a warning if it isn't yet fully supported and tested with Toolkit. To disable the warning - dialog for the version you are testing, it is recomended that you set this + dialog for the version you are testing, it is recommended that you set this value to the current major version + 1." default_value: 10 diff --git a/plugins/basic/info.yml b/plugins/basic/info.yml index d246c89..fdc367b 100755 --- a/plugins/basic/info.yml +++ b/plugins/basic/info.yml @@ -12,11 +12,11 @@ base_configuration: # The default configuration that the plugin should use. # For documentation and details, see - # http://developer.shotgunsoftware.com/tk-core/bootstrap.html#sgtk.bootstrap.ToolkitManager.base_configuration + # http://developer.shotgridsoftware.com/tk-core/bootstrap.html#sgtk.bootstrap.ToolkitManager.base_configuration # # This is expressed in the form of a Toolkit Descriptor. For more # information about Toolkit descriptors, see - # http://developer.shotgunsoftware.com/tk-core/descriptor.html + # http://developer.shotgridsoftware.com/tk-core/descriptor.html # # If your descriptor supports a version token and you want it to # always use the latest version available, simply omit the version token. @@ -25,7 +25,7 @@ base_configuration: # The Plugin Id helps uniquely identify this plugin and can be # used to override and customize it. For more information, see -# http://developer.shotgunsoftware.com/tk-core/bootstrap.html#sgtk.bootstrap.ToolkitManager.plugin_id +# http://developer.shotgridsoftware.com/tk-core/bootstrap.html#sgtk.bootstrap.ToolkitManager.plugin_id # # When the plugin is built, this file will be converted into a manifest.py file # and located in a python module named based on the plugin id in order to ensure diff --git a/python/tk_nuke/context.py b/python/tk_nuke/context.py index 8c2b8d3..e068b11 100755 --- a/python/tk_nuke/context.py +++ b/python/tk_nuke/context.py @@ -189,7 +189,10 @@ def _get_context_from_script(self, script): """ tk = tank.tank_from_path(script) - context = tk.context_from_path(script, previous_context=self.engine.context,) + context = tk.context_from_path( + script, + previous_context=self.engine.context, + ) if context.project is None: raise tank.TankError( @@ -233,7 +236,8 @@ def _on_save_callback(self): # Extract a new context based on the file and change to that # context. new_context = tk.context_from_path( - file_name, previous_context=self.context, + file_name, + previous_context=self.context, ) self.change_context(new_context) @@ -270,7 +274,8 @@ def _startup_node_callback(self): return new_ctx = tk.context_from_path( - file_name, previous_context=self.context, + file_name, + previous_context=self.context, ) # Now change the context for the engine and apps. @@ -346,7 +351,8 @@ def register_events(self, reregister=False): # Event for context switching from Hiero to Nuke. hiero.core.events.registerInterest( - hiero.core.events.EventType.kContextChanged, self._eventHandler, + hiero.core.events.EventType.kContextChanged, + self._eventHandler, ) for func_desc in self._event_desc: @@ -381,7 +387,8 @@ def unregister_events(self, only=None): import hiero.core hiero.core.events.unregisterInterest( - hiero.core.events.EventType.kContextChanged, self._eventHandler, + hiero.core.events.EventType.kContextChanged, + self._eventHandler, ) func_descs = only or self._event_desc diff --git a/python/tk_nuke/menu_generation.py b/python/tk_nuke/menu_generation.py index 5d87cfe..c159c70 100755 --- a/python/tk_nuke/menu_generation.py +++ b/python/tk_nuke/menu_generation.py @@ -251,16 +251,19 @@ def _create_hiero_menu(self, add_commands=True, commands=None): # Register for the interesting events. hiero.core.events.registerInterest( - "kShowContextMenu/kBin", self.eventHandler, + "kShowContextMenu/kBin", + self.eventHandler, ) hiero.core.events.registerInterest( - "kShowContextMenu/kTimeline", self.eventHandler, + "kShowContextMenu/kTimeline", + self.eventHandler, ) # Note that the kViewer works differently than the other things # (returns a hiero.ui.Viewer object: http://docs.thefoundry.co.uk/hiero/10/hieropythondevguide/api/api_ui.html#hiero.ui.Viewer) # so we cannot support this easily using the same principles as for the other things. hiero.core.events.registerInterest( - "kShowContextMenu/kSpreadsheet", self.eventHandler, + "kShowContextMenu/kSpreadsheet", + self.eventHandler, ) self._menu_handle.addSeparator() @@ -310,16 +313,19 @@ def destroy_menu(self): # Register for the interesting events. hiero.core.events.unregisterInterest( - "kShowContextMenu/kBin", self.eventHandler, + "kShowContextMenu/kBin", + self.eventHandler, ) hiero.core.events.unregisterInterest( - "kShowContextMenu/kTimeline", self.eventHandler, + "kShowContextMenu/kTimeline", + self.eventHandler, ) # Note that the kViewer works differently than the other things # (returns a hiero.ui.Viewer object: http://docs.thefoundry.co.uk/hiero/10/hieropythondevguide/api/api_ui.html#hiero.ui.Viewer) # so we cannot support this easily using the same principles as for the other things. hiero.core.events.unregisterInterest( - "kShowContextMenu/kSpreadsheet", self.eventHandler, + "kShowContextMenu/kSpreadsheet", + self.eventHandler, ) def eventHandler(self, event): @@ -494,7 +500,9 @@ def create_disabled_menu(self, cmd_name, msg): callback = lambda m=msg: nuke.message(m) cmd = HieroAppCommand( - self.engine, cmd_name, dict(properties=dict(), callback=callback), + self.engine, + cmd_name, + dict(properties=dict(), callback=callback), ) cmd.add_command_to_menu(self._menu_handle, icon=self._shotgun_logo_blue) @@ -612,7 +620,8 @@ def create_menu(self, add_commands=True): if cmd.type == "panel": # First make sure the Shotgun pane menu exists. pane_menu = nuke.menu("Pane").addMenu( - "ShotGrid", icon=self._shotgun_logo, + "ShotGrid", + icon=self._shotgun_logo, ) # Now set up the callback. cmd.add_command_to_pane_menu(pane_menu) @@ -634,7 +643,9 @@ def create_disabled_menu(self, cmd_name, msg): callback = lambda m=msg: nuke.message(m) cmd = NukeAppCommand( - self.engine, cmd_name, dict(properties=dict(), callback=callback), + self.engine, + cmd_name, + dict(properties=dict(), callback=callback), ) cmd.add_command_to_menu(self._menu_handle, icon=self._shotgun_logo_blue) diff --git a/python/tk_nuke_qt/panels.py b/python/tk_nuke_qt/panels.py index cc525b6..be09fc4 100755 --- a/python/tk_nuke_qt/panels.py +++ b/python/tk_nuke_qt/panels.py @@ -51,7 +51,12 @@ def __init__(self, bundle, dialog_name, panel_id, widget_class, *args, **kwargs) # we cannot pass parameters to the constructor of our wrapper class # directly, so instead pass them via a special class method ToolkitWidgetWrapper.set_init_parameters( - widget_class, panel_id, bundle, self, args, kwargs, + widget_class, + panel_id, + bundle, + self, + args, + kwargs, ) # Run parent constructor diff --git a/resources/alert_icon.png b/resources/alert_icon.png new file mode 100644 index 0000000..8b9dd05 Binary files /dev/null and b/resources/alert_icon.png differ diff --git a/resources/sg_logo_80px.png b/resources/sg_logo_80px.png new file mode 100644 index 0000000..f4a3629 Binary files /dev/null and b/resources/sg_logo_80px.png differ diff --git a/resources/sg_logo_blue_32px.png b/resources/sg_logo_blue_32px.png new file mode 100644 index 0000000..c404229 Binary files /dev/null and b/resources/sg_logo_blue_32px.png differ diff --git a/resources/sg_logo_dark_80px.png b/resources/sg_logo_dark_80px.png new file mode 100644 index 0000000..68cec57 Binary files /dev/null and b/resources/sg_logo_dark_80px.png differ diff --git a/tests/test_startup.py b/tests/test_startup.py index d84f5b1..119a505 100755 --- a/tests/test_startup.py +++ b/tests/test_startup.py @@ -11,6 +11,7 @@ from __future__ import with_statement from __future__ import print_function import os +import sys from tank_test.tank_test_base import TankTestBase from tank_test.tank_test_base import setUpModule # noqa @@ -151,14 +152,37 @@ def _recursive_split(self, path): directory, basename = os.path.split(path) return self._recursive_split(directory) + [basename] + def _glob_wrapper39(self, directory, dironly): + """ + This is a mocked implementation of glob._iterdir for Python >= 3.9. + This method fakes a folder hierarchy. + """ + tokens = self._recursive_split(directory) + # Start at the root of the mocked file system + current_depth = self._get_os_neutral_hierarchy() + for t in tokens: + # Unit test should not be asking for folders outside of the DCC hierarchy. + self.assertIn(t, current_depth) + # Remember where we are in the current hierarchy. + current_depth = current_depth[t] + current_depth_gen = (file for file in current_depth) + + # We've reached the folder we wanted, build a list. + # We're using dicts for intermediary folders and lists for leaf folders so iterate + # on the items to get all the names. + return current_depth_gen + def _glob_wrapper(self, directory, dironly): """ This is a mocked implementation of glob._iterdir. This method fakes a folder hierarchy. """ + tokens = self._recursive_split(directory) # Start at the root of the mocked file system current_depth = self._get_os_neutral_hierarchy() + # Ensure we are getting back the right variations. + for t in tokens: # Unit test should not be asking for folders outside of the DCC hierarchy. self.assertIn(t, current_depth) @@ -232,9 +256,15 @@ def _mock_folder_listing(self): if "TK_NO_FOLDER_MOCKING" not in os.environ: # In Python 3 glob doesn't use os.listdir to help iterate over the folders # It uses it's own _iterdir method, which still produces the same output. - if six.PY3: + + if sys.version_info[0:2] >= (3, 9): + with mock.patch("glob._iterdir", wraps=self._glob_wrapper39): + yield + + elif six.PY3: with mock.patch("glob._iterdir", wraps=self._glob_wrapper): yield + else: with mock.patch("os.listdir", wraps=self._os_listdir_wrapper): yield @@ -256,7 +286,8 @@ def _get_os_neutral_hierarchy(cls): return cls._mac_mock_hierarchy def _get_plugin_environment( - self, dcc_path, + self, + dcc_path, ): """ Returns the expected environment variables dictionary for a plugin.