Merge branch 'develop' into PYPE-1930_Create-SFTP-provider

This commit is contained in:
Petr Kalis 2021-10-01 18:58:16 +02:00 committed by GitHub
commit cac3fb81c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 645 additions and 114 deletions

View file

@ -5,6 +5,8 @@ from __future__ import absolute_import
import pyblish.api
import openpype.api
from maya import cmds
class SelectInvalidInstances(pyblish.api.Action):
"""Select invalid instances in Outliner."""
@ -18,13 +20,12 @@ class SelectInvalidInstances(pyblish.api.Action):
# Get the errored instances
failed = []
for result in context.data["results"]:
if result["error"] is None:
continue
if result["instance"] is None:
continue
if result["instance"] in failed:
continue
if result["plugin"] != plugin:
if (
result["error"] is None
or result["instance"] is None
or result["instance"] in failed
or result["plugin"] != plugin
):
continue
failed.append(result["instance"])
@ -44,25 +45,10 @@ class SelectInvalidInstances(pyblish.api.Action):
self.deselect()
def select(self, instances):
if "nuke" in pyblish.api.registered_hosts():
import avalon.nuke.lib
import nuke
avalon.nuke.lib.select_nodes(
[nuke.toNode(str(x)) for x in instances]
)
if "maya" in pyblish.api.registered_hosts():
from maya import cmds
cmds.select(instances, replace=True, noExpand=True)
cmds.select(instances, replace=True, noExpand=True)
def deselect(self):
if "nuke" in pyblish.api.registered_hosts():
import avalon.nuke.lib
avalon.nuke.lib.reset_selection()
if "maya" in pyblish.api.registered_hosts():
from maya import cmds
cmds.select(deselect=True)
cmds.select(deselect=True)
class RepairSelectInvalidInstances(pyblish.api.Action):
@ -92,23 +78,14 @@ class RepairSelectInvalidInstances(pyblish.api.Action):
context_asset = context.data["assetEntity"]["name"]
for instance in instances:
if "nuke" in pyblish.api.registered_hosts():
import openpype.hosts.nuke.api as nuke_api
origin_node = instance[0]
nuke_api.lib.recreate_instance(
origin_node, avalon_data={"asset": context_asset}
)
else:
self.set_attribute(instance, context_asset)
self.set_attribute(instance, context_asset)
def set_attribute(self, instance, context_asset):
if "maya" in pyblish.api.registered_hosts():
from maya import cmds
cmds.setAttr(
instance.data.get("name") + ".asset",
context_asset,
type="string"
)
cmds.setAttr(
instance.data.get("name") + ".asset",
context_asset,
type="string"
)
class ValidateInstanceInContext(pyblish.api.InstancePlugin):
@ -124,7 +101,7 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin):
order = openpype.api.ValidateContentsOrder
label = "Instance in same Context"
optional = True
hosts = ["maya", "nuke"]
hosts = ["maya"]
actions = [SelectInvalidInstances, RepairSelectInvalidInstances]
def process(self, instance):

View file

@ -0,0 +1,47 @@
import pyblish.api
import maya.cmds as cmds
import openpype.api
import os
class ValidateLoadedPlugin(pyblish.api.ContextPlugin):
"""Ensure there are no unauthorized loaded plugins"""
label = "Loaded Plugin"
order = pyblish.api.ValidatorOrder
host = ["maya"]
actions = [openpype.api.RepairContextAction]
@classmethod
def get_invalid(cls, context):
invalid = []
loaded_plugin = cmds.pluginInfo(query=True, listPlugins=True)
# get variable from OpenPype settings
whitelist_native_plugins = cls.whitelist_native_plugins
authorized_plugins = cls.authorized_plugins or []
for plugin in loaded_plugin:
if not whitelist_native_plugins and os.getenv('MAYA_LOCATION') \
in cmds.pluginInfo(plugin, query=True, path=True):
continue
if plugin not in authorized_plugins:
invalid.append(plugin)
return invalid
def process(self, context):
invalid = self.get_invalid(context)
if invalid:
raise RuntimeError(
"Found forbidden plugin name: {}".format(", ".join(invalid))
)
@classmethod
def repair(cls, context):
"""Unload forbidden plugins"""
for plugin in cls.get_invalid(context):
cmds.pluginInfo(plugin, edit=True, autoload=False)
cmds.unloadPlugin(plugin, force=True)

View file

@ -295,7 +295,7 @@ def add_button_write_to_read(node):
def create_write_node(name, data, input=None, prenodes=None,
review=True, linked_knobs=None):
review=True, linked_knobs=None, farm=True):
''' Creating write node which is group node
Arguments:
@ -421,7 +421,15 @@ def create_write_node(name, data, input=None, prenodes=None,
))
continue
if knob and value:
if not knob and not value:
continue
log.info((knob, value))
if isinstance(value, str):
if "[" in value:
now_node[knob].setExpression(value)
else:
now_node[knob].setValue(value)
# connect to previous node
@ -466,7 +474,7 @@ def create_write_node(name, data, input=None, prenodes=None,
# imprinting group node
anlib.set_avalon_knob_data(GN, data["avalon"])
anlib.add_publish_knob(GN)
add_rendering_knobs(GN)
add_rendering_knobs(GN, farm)
if review:
add_review_knob(GN)
@ -526,7 +534,7 @@ def create_write_node(name, data, input=None, prenodes=None,
return GN
def add_rendering_knobs(node):
def add_rendering_knobs(node, farm=True):
''' Adds additional rendering knobs to given node
Arguments:
@ -535,9 +543,13 @@ def add_rendering_knobs(node):
Return:
node (obj): with added knobs
'''
knob_options = [
"Use existing frames", "Local"]
if farm:
knob_options.append("On farm")
if "render" not in node.knobs():
knob = nuke.Enumeration_Knob("render", "", [
"Use existing frames", "Local", "On farm"])
knob = nuke.Enumeration_Knob("render", "", knob_options)
knob.clearFlag(nuke.STARTLINE)
node.addKnob(knob)
return node

View file

@ -0,0 +1,141 @@
from collections import OrderedDict
from openpype.hosts.nuke.api import (
plugin,
lib)
import nuke
class CreateWriteStill(plugin.PypeCreator):
# change this to template preset
name = "WriteStillFrame"
label = "Create Write Still Image"
hosts = ["nuke"]
n_class = "Write"
family = "still"
icon = "image"
defaults = [
"ImageFrame{:0>4}".format(nuke.frame()),
"MPFrame{:0>4}".format(nuke.frame()),
"LayoutFrame{:0>4}".format(nuke.frame())
]
def __init__(self, *args, **kwargs):
super(CreateWriteStill, self).__init__(*args, **kwargs)
data = OrderedDict()
data["family"] = self.family
data["families"] = self.n_class
for k, v in self.data.items():
if k not in data.keys():
data.update({k: v})
self.data = data
self.nodes = nuke.selectedNodes()
self.log.debug("_ self.data: '{}'".format(self.data))
def process(self):
inputs = []
outputs = []
instance = nuke.toNode(self.data["subset"])
selected_node = None
# use selection
if (self.options or {}).get("useSelection"):
nodes = self.nodes
if not (len(nodes) < 2):
msg = ("Select only one node. "
"The node you want to connect to, "
"or tick off `Use selection`")
self.log.error(msg)
nuke.message(msg)
return
if len(nodes) == 0:
msg = (
"No nodes selected. Please select a single node to connect"
" to or tick off `Use selection`"
)
self.log.error(msg)
nuke.message(msg)
return
selected_node = nodes[0]
inputs = [selected_node]
outputs = selected_node.dependent()
if instance:
if (instance.name() in selected_node.name()):
selected_node = instance.dependencies()[0]
# if node already exist
if instance:
# collect input / outputs
inputs = instance.dependencies()
outputs = instance.dependent()
selected_node = inputs[0]
# remove old one
nuke.delete(instance)
# recreate new
write_data = {
"nodeclass": self.n_class,
"families": [self.family],
"avalon": self.data
}
# add creator data
creator_data = {"creator": self.__class__.__name__}
self.data.update(creator_data)
write_data.update(creator_data)
self.log.info("Adding template path from plugin")
write_data.update({
"fpath_template": (
"{work}/renders/nuke/{subset}/{subset}.{ext}")})
_prenodes = [
{
"name": "FrameHold01",
"class": "FrameHold",
"knobs": [
("first_frame", nuke.frame())
],
"dependent": None
}
]
write_node = lib.create_write_node(
self.name,
write_data,
input=selected_node,
review=False,
prenodes=_prenodes,
farm=False,
linked_knobs=["channels", "___", "first", "last", "use_limit"])
# relinking to collected connections
for i, input in enumerate(inputs):
write_node.setInput(i, input)
write_node.autoplace()
for output in outputs:
output.setInput(0, write_node)
# link frame hold to group node
write_node.begin()
for n in nuke.allNodes():
# get write node
if n.Class() in "Write":
w_node = n
write_node.end()
w_node["use_limit"].setValue(True)
w_node["first"].setValue(nuke.frame())
w_node["last"].setValue(nuke.frame())
return write_node

View file

@ -13,7 +13,7 @@ class LoadImage(api.Loader):
"""Load still image into Nuke"""
families = ["render", "source", "plate", "review", "image"]
representations = ["exr", "dpx", "jpg", "jpeg", "png", "psd"]
representations = ["exr", "dpx", "jpg", "jpeg", "png", "psd", "tiff"]
label = "Load Image"
order = -10

View file

@ -17,7 +17,7 @@ class NukeRenderLocal(openpype.api.Extractor):
order = pyblish.api.ExtractorOrder
label = "Render Local"
hosts = ["nuke"]
families = ["render.local", "prerender.local"]
families = ["render.local", "prerender.local", "still.local"]
def process(self, instance):
families = instance.data["families"]
@ -66,13 +66,23 @@ class NukeRenderLocal(openpype.api.Extractor):
instance.data["representations"] = []
collected_frames = os.listdir(out_dir)
repre = {
'name': ext,
'ext': ext,
'frameStart': "%0{}d".format(len(str(last_frame))) % first_frame,
'files': collected_frames,
"stagingDir": out_dir
}
if len(collected_frames) == 1:
repre = {
'name': ext,
'ext': ext,
'files': collected_frames.pop(),
"stagingDir": out_dir
}
else:
repre = {
'name': ext,
'ext': ext,
'frameStart': "%0{}d".format(
len(str(last_frame))) % first_frame,
'files': collected_frames,
"stagingDir": out_dir
}
instance.data["representations"].append(repre)
self.log.info("Extracted instance '{0}' to: {1}".format(
@ -89,6 +99,9 @@ class NukeRenderLocal(openpype.api.Extractor):
instance.data['family'] = 'prerender'
families.remove('prerender.local')
families.insert(0, "prerender")
elif "still.local" in families:
instance.data['family'] = 'image'
families.remove('still.local')
instance.data["families"] = families
collections, remainder = clique.assemble(collected_frames)

View file

@ -64,7 +64,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
)
if [fm for fm in _families_test
if fm in ["render", "prerender"]]:
if fm in ["render", "prerender", "still"]]:
if "representations" not in instance.data:
instance.data["representations"] = list()
@ -100,7 +100,13 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
frame_start_str, frame_slate_str)
collected_frames.insert(0, slate_frame)
representation['files'] = collected_frames
if collected_frames_len == 1:
representation['files'] = collected_frames.pop()
if "still" in _families_test:
instance.data['family'] = 'image'
instance.data["families"].remove('still')
else:
representation['files'] = collected_frames
instance.data["representations"].append(representation)
except Exception:
instance.data["representations"].append(representation)

View file

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
"""Validate if instance asset is the same as context asset."""
from __future__ import absolute_import
import nuke
import pyblish.api
import openpype.api
import avalon.nuke.lib
import openpype.hosts.nuke.api as nuke_api
class SelectInvalidInstances(pyblish.api.Action):
"""Select invalid instances in Outliner."""
label = "Select Instances"
icon = "briefcase"
on = "failed"
def process(self, context, plugin):
"""Process invalid validators and select invalid instances."""
# Get the errored instances
failed = []
for result in context.data["results"]:
if (
result["error"] is None
or result["instance"] is None
or result["instance"] in failed
or result["plugin"] != plugin
):
continue
failed.append(result["instance"])
# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(failed, plugin)
if instances:
self.log.info(
"Selecting invalid nodes: %s" % ", ".join(
[str(x) for x in instances]
)
)
self.select(instances)
else:
self.log.info("No invalid nodes found.")
self.deselect()
def select(self, instances):
avalon.nuke.lib.select_nodes(
[nuke.toNode(str(x)) for x in instances]
)
def deselect(self):
avalon.nuke.lib.reset_selection()
class RepairSelectInvalidInstances(pyblish.api.Action):
"""Repair the instance asset."""
label = "Repair"
icon = "wrench"
on = "failed"
def process(self, context, plugin):
# Get the errored instances
failed = []
for result in context.data["results"]:
if (
result["error"] is None
or result["instance"] is None
or result["instance"] in failed
or result["plugin"] != plugin
):
continue
failed.append(result["instance"])
# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(failed, plugin)
context_asset = context.data["assetEntity"]["name"]
for instance in instances:
origin_node = instance[0]
nuke_api.lib.recreate_instance(
origin_node, avalon_data={"asset": context_asset}
)
class ValidateInstanceInContext(pyblish.api.InstancePlugin):
"""Validator to check if instance asset match context asset.
When working in per-shot style you always publish data in context of
current asset (shot). This validator checks if this is so. It is optional
so it can be disabled when needed.
Action on this validator will select invalid instances in Outliner.
"""
order = openpype.api.ValidateContentsOrder
label = "Instance in same Context"
hosts = ["nuke"]
actions = [SelectInvalidInstances, RepairSelectInvalidInstances]
optional = True
def process(self, instance):
asset = instance.data.get("asset")
context_asset = instance.context.data["assetEntity"]["name"]
msg = "{} has asset {}".format(instance.name, asset)
assert asset == context_asset, msg

View file

@ -55,7 +55,7 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin):
""" Validates file output. """
order = pyblish.api.ValidatorOrder + 0.1
families = ["render", "prerender"]
families = ["render", "prerender", "still"]
label = "Validate rendered frame"
hosts = ["nuke", "nukestudio"]
@ -71,6 +71,9 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin):
self.log.error(msg)
raise ValidationException(msg)
if isinstance(repre["files"], str):
return
collections, remainder = clique.assemble(repre["files"])
self.log.info("collections: {}".format(str(collections)))
self.log.info("remainder: {}".format(str(remainder)))

View file

@ -22,6 +22,7 @@ class CollectAvalonEntities(pyblish.api.ContextPlugin):
io.install()
project_name = api.Session["AVALON_PROJECT"]
asset_name = api.Session["AVALON_ASSET"]
task_name = api.Session["AVALON_TASK"]
project_entity = io.find_one({
"type": "project",
@ -48,6 +49,12 @@ class CollectAvalonEntities(pyblish.api.ContextPlugin):
data = asset_entity['data']
# Task type
asset_tasks = data.get("tasks") or {}
task_info = asset_tasks.get(task_name) or {}
task_type = task_info.get("type")
context.data["taskType"] = task_type
frame_start = data.get("frameStart")
if frame_start is None:
frame_start = 1

View file

@ -226,7 +226,8 @@ class ExtractBurnin(openpype.api.Extractor):
"options": copy.deepcopy(burnin_options),
"values": burnin_values,
"full_input_path": temp_data["full_input_paths"][0],
"first_frame": temp_data["first_frame"]
"first_frame": temp_data["first_frame"],
"ffmpeg_cmd": new_repre.get("ffmpeg_cmd", "")
}
self.log.debug(

View file

@ -30,8 +30,8 @@ class ExtractReview(pyblish.api.InstancePlugin):
otherwise the representation is ignored.
All new representations are created and encoded by ffmpeg following
presets found in `pype-config/presets/plugins/global/
publish.json:ExtractReview:outputs`.
presets found in OpenPype Settings interface at
`project_settings/global/publish/ExtractReview/profiles:outputs`.
"""
label = "Extract Review"
@ -241,7 +241,8 @@ class ExtractReview(pyblish.api.InstancePlugin):
"outputName": output_name,
"outputDef": output_def,
"frameStartFtrack": temp_data["output_frame_start"],
"frameEndFtrack": temp_data["output_frame_end"]
"frameEndFtrack": temp_data["output_frame_end"],
"ffmpeg_cmd": subprcs_cmd
})
# Force to pop these key if are in new repre

View file

@ -1,6 +1,5 @@
import pyblish.api
from openpype.api import get_system_settings
from openpype.lib import change_timer_to_current_context
@ -10,6 +9,6 @@ class StartTimer(pyblish.api.ContextPlugin):
hosts = ["*"]
def process(self, context):
modules_settings = get_system_settings()["modules"]
modules_settings = context.data["system_settings"]["modules"]
if modules_settings["timers_manager"]["disregard_publishing"]:
change_timer_to_current_context()

View file

@ -3,8 +3,6 @@ import requests
import pyblish.api
from openpype.api import get_system_settings
class StopTimer(pyblish.api.ContextPlugin):
label = "Stop Timer"
@ -12,7 +10,7 @@ class StopTimer(pyblish.api.ContextPlugin):
hosts = ["*"]
def process(self, context):
modules_settings = get_system_settings()["modules"]
modules_settings = context.data["system_settings"]["modules"]
if modules_settings["timers_manager"]["disregard_publishing"]:
webserver_url = os.environ.get("OPENPYPE_WEBSERVER_URL")
rest_api_url = "{}/timers_manager/stop_timer".format(webserver_url)

View file

@ -1,7 +1,5 @@
import pyblish.api
import openpype.lib
from avalon.tools import cbsceneinventory
class ShowInventory(pyblish.api.Action):
@ -11,7 +9,9 @@ class ShowInventory(pyblish.api.Action):
on = "failed"
def process(self, context, plugin):
cbsceneinventory.show()
from avalon.tools import sceneinventory
sceneinventory.show()
class ValidateContainers(pyblish.api.ContextPlugin):

View file

@ -1,5 +1,7 @@
import pyblish.api
import os
import pyblish.api
from openpype.lib import filter_profiles
class ValidateIntent(pyblish.api.ContextPlugin):
@ -12,20 +14,49 @@ class ValidateIntent(pyblish.api.ContextPlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Intent"
# TODO: this should be off by default and only activated viac config
tasks = ["animation"]
hosts = ["harmony"]
if os.environ.get("AVALON_TASK") not in tasks:
active = False
enabled = False
# Can be modified by settings
profiles = [{
"hosts": [],
"task_types": [],
"tasks": [],
"validate": False
}]
def process(self, context):
# Skip if there are no profiles
validate = True
if self.profiles:
# Collect data from context
task_name = context.data.get("task")
task_type = context.data.get("taskType")
host_name = context.data.get("hostName")
filter_data = {
"hosts": host_name,
"task_types": task_type,
"tasks": task_name
}
matching_profile = filter_profiles(
self.profiles, filter_data, logger=self.log
)
if matching_profile:
validate = matching_profile["validate"]
if not validate:
self.log.debug((
"Validation of intent was skipped."
" Matching profile for current context disabled validation."
))
return
msg = (
"Please make sure that you select the intent of this publish."
)
intent = context.data.get("intent")
self.log.debug(intent)
assert intent, msg
intent = context.data.get("intent") or {}
self.log.debug(str(intent))
intent_value = intent.get("value")
assert intent is not "", msg
if not intent_value:
raise AssertionError(msg)

View file

@ -12,6 +12,9 @@ class ValidateVersion(pyblish.api.InstancePlugin):
label = "Validate Version"
hosts = ["nuke", "maya", "blender", "standalonepublisher"]
optional = False
active = True
def process(self, instance):
version = instance.data.get("version")
latest_version = instance.data.get("latestVersion")

View file

@ -69,7 +69,7 @@ def get_fps(str_value):
return str(fps)
def _prores_codec_args(ffprobe_data):
def _prores_codec_args(ffprobe_data, source_ffmpeg_cmd):
output = []
tags = ffprobe_data.get("tags") or {}
@ -108,14 +108,24 @@ def _prores_codec_args(ffprobe_data):
return output
def _h264_codec_args(ffprobe_data):
def _h264_codec_args(ffprobe_data, source_ffmpeg_cmd):
output = []
output.extend(["-codec:v", "h264"])
bit_rate = ffprobe_data.get("bit_rate")
if bit_rate:
output.extend(["-b:v", bit_rate])
# Use arguments from source if are available source arguments
if source_ffmpeg_cmd:
copy_args = (
"-crf",
"-b:v", "-vb",
"-minrate", "-minrate:",
"-maxrate", "-maxrate:",
"-bufsize", "-bufsize:"
)
args = source_ffmpeg_cmd.split(" ")
for idx, arg in enumerate(args):
if arg in copy_args:
output.extend([arg, args[idx + 1]])
pix_fmt = ffprobe_data.get("pix_fmt")
if pix_fmt:
@ -127,15 +137,15 @@ def _h264_codec_args(ffprobe_data):
return output
def get_codec_args(ffprobe_data):
def get_codec_args(ffprobe_data, source_ffmpeg_cmd):
codec_name = ffprobe_data.get("codec_name")
# Codec "prores"
if codec_name == "prores":
return _prores_codec_args(ffprobe_data)
return _prores_codec_args(ffprobe_data, source_ffmpeg_cmd)
# Codec "h264"
if codec_name == "h264":
return _h264_codec_args(ffprobe_data)
return _h264_codec_args(ffprobe_data, source_ffmpeg_cmd)
output = []
if codec_name:
@ -469,7 +479,7 @@ def example(input_path, output_path):
def burnins_from_data(
input_path, output_path, data,
codec_data=None, options=None, burnin_values=None, overwrite=True,
full_input_path=None, first_frame=None
full_input_path=None, first_frame=None, source_ffmpeg_cmd=None
):
"""This method adds burnins to video/image file based on presets setting.
@ -647,7 +657,7 @@ def burnins_from_data(
else:
ffprobe_data = burnin._streams[0]
ffmpeg_args.extend(get_codec_args(ffprobe_data))
ffmpeg_args.extend(get_codec_args(ffprobe_data, source_ffmpeg_cmd))
# Use group one (same as `-intra` argument, which is deprecated)
ffmpeg_args_str = " ".join(ffmpeg_args)
@ -670,6 +680,7 @@ if __name__ == "__main__":
options=in_data.get("options"),
burnin_values=in_data.get("values"),
full_input_path=in_data.get("full_input_path"),
first_frame=in_data.get("first_frame")
first_frame=in_data.get("first_frame"),
source_ffmpeg_cmd=in_data.get("ffmpeg_cmd")
)
print("* Burnin script has finished")

View file

@ -124,9 +124,47 @@
"value": "True"
}
]
},
{
"plugins": [
"CreateWriteStill"
],
"nukeNodeClass": "Write",
"knobs": [
{
"name": "file_type",
"value": "tiff"
},
{
"name": "datatype",
"value": "16 bit"
},
{
"name": "compression",
"value": "Deflate"
},
{
"name": "tile_color",
"value": "0x23ff00ff"
},
{
"name": "channels",
"value": "rgb"
},
{
"name": "colorspace",
"value": "sRGB"
},
{
"name": "create_directories",
"value": "True"
}
]
}
],
"customNodes": []
"customNodes": [
]
},
"regexInputs": {
"inputs": [

View file

@ -6,7 +6,12 @@
},
"ValidateVersion": {
"enabled": true,
"optional": false
"optional": false,
"active": true
},
"ValidateIntent": {
"enabled": false,
"profiles": []
},
"IntegrateHeroVersion": {
"enabled": true,

View file

@ -156,6 +156,11 @@
"CollectMayaRender": {
"sync_workfile_version": false
},
"ValidateInstanceInContext": {
"enabled": true,
"optional": true,
"active": true
},
"ValidateContainers": {
"enabled": true,
"optional": true,
@ -169,6 +174,11 @@
"enabled": false,
"attributes": {}
},
"ValidateLoadedPlugin": {
"enabled": false,
"whitelist_native_plugins": false,
"authorized_plugins": []
},
"ValidateRenderSettings": {
"arnold_render_attributes": [],
"vray_render_attributes": [],

View file

@ -38,6 +38,11 @@
"render"
]
},
"ValidateInstanceInContext": {
"enabled": true,
"optional": true,
"active": true
},
"ValidateContainers": {
"enabled": true,
"optional": true,
@ -127,7 +132,8 @@
"jpg",
"jpeg",
"png",
"psd"
"psd",
"tiff"
],
"node_name_template": "{class_name}_{ext}"
},

View file

@ -24,13 +24,22 @@
}
]
},
{
"type": "schema_template",
"name": "template_publish_plugin",
"template_data": [
{
"key": "ValidateVersion",
"label": "Validate Version"
}
]
},
{
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ValidateVersion",
"label": "Validate Version",
"label": "Validate Intent",
"key": "ValidateIntent",
"is_group": true,
"checkbox_key": "enabled",
"children": [
{
"type": "boolean",
@ -38,9 +47,43 @@
"label": "Enabled"
},
{
"type": "boolean",
"key": "optional",
"label": "Optional"
"type": "label",
"label": "Validate if Publishing intent was selected. It is possible to disable validation for specific publishing context with profiles."
},
{
"type": "list",
"collapsible": true,
"key": "profiles",
"object_type": {
"type": "dict",
"children": [
{
"key": "hosts",
"label": "Host names",
"type": "hosts-enum",
"multiselection": true
},
{
"key": "task_types",
"label": "Task types",
"type": "task-types-enum"
},
{
"key": "tasks",
"label": "Task names",
"type": "list",
"object_type": "text"
},
{
"type": "separator"
},
{
"key": "validate",
"label": "Validate",
"type": "boolean"
}
]
}
}
]
},

View file

@ -28,6 +28,16 @@
"type": "label",
"label": "Validators"
},
{
"type": "schema_template",
"name": "template_publish_plugin",
"template_data": [
{
"key": "ValidateInstanceInContext",
"label": "Validate Instance In Context"
}
]
},
{
"type": "schema_template",
"name": "template_publish_plugin",
@ -82,6 +92,32 @@
]
},
{
"type": "dict",
"collapsible": true,
"key": "ValidateLoadedPlugin",
"label": "Validate Loaded Plugin",
"checkbox_key": "enabled",
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "boolean",
"key": "whitelist_native_plugins",
"label": "Whitelist Maya Native Plugins"
},
{
"type": "list",
"key": "authorized_plugins",
"label": "Authorized plugins",
"object_type": "text"
}
]
},
{
"type": "dict",
"collapsible": true,

View file

@ -50,6 +50,16 @@
"type": "label",
"label": "Validators"
},
{
"type": "schema_template",
"name": "template_publish_plugin",
"template_data": [
{
"key": "ValidateInstanceInContext",
"label": "Validate Instance In Context"
}
]
},
{
"type": "schema_template",
"name": "template_publish_plugin",

45
poetry.lock generated
View file

@ -1152,7 +1152,7 @@ python-versions = "*"
[[package]]
name = "pywin32"
version = "300"
version = "301"
description = "Python for Window Extensions"
category = "main"
optional = false
@ -1975,12 +1975,22 @@ log4mongo = [
{file = "log4mongo-1.7.0.tar.gz", hash = "sha256:dc374617206162a0b14167fbb5feac01dbef587539a235dadba6200362984a68"},
]
markupsafe = [
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
{file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
{file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
@ -1989,14 +1999,21 @@ markupsafe = [
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
@ -2006,6 +2023,9 @@ markupsafe = [
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
@ -2306,6 +2326,7 @@ pynput = [
]
pyobjc-core = [
{file = "pyobjc-core-7.3.tar.gz", hash = "sha256:5081aedf8bb40aac1a8ad95adac9e44e148a882686ded614adf46bb67fd67574"},
{file = "pyobjc_core-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a1f1e6b457127cbf2b5bd2b94520a7c89fb590b739911eadb2b0499a3a5b0e6f"},
{file = "pyobjc_core-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e93ad769a20b908778fe950f62a843a6d8f0fa71996e5f3cc9fab5ae7d17771"},
{file = "pyobjc_core-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f63fd37bbf3785af4ddb2f86cad5ca81c62cfc7d1c0099637ca18343c3656c1"},
{file = "pyobjc_core-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9b1311f72f2e170742a7ee3a8149f52c35158dc024a21e88d6f1e52ba5d718b"},
@ -2314,6 +2335,7 @@ pyobjc-core = [
]
pyobjc-framework-cocoa = [
{file = "pyobjc-framework-Cocoa-7.3.tar.gz", hash = "sha256:b18d05e7a795a3455ad191c3e43d6bfa673c2a4fd480bb1ccf57191051b80b7e"},
{file = "pyobjc_framework_Cocoa-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1e31376806e5de883a1d7c7c87d9ff2a8b09fc05d267e0dfce6e42409fb70c67"},
{file = "pyobjc_framework_Cocoa-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9edffdfa6dd1f71f21b531c3e61fdd3e4d5d3bf6c5a528c98e88828cd60bac11"},
{file = "pyobjc_framework_Cocoa-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:35a6340437a4e0109a302150b7d1f6baf57004ccf74834f9e6062fcafe2fd8d7"},
{file = "pyobjc_framework_Cocoa-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c3886f2608ab3ed02482f8b2ebf9f782b324c559e84b52cfd92dba8a1109872"},
@ -2322,6 +2344,7 @@ pyobjc-framework-cocoa = [
]
pyobjc-framework-quartz = [
{file = "pyobjc-framework-Quartz-7.3.tar.gz", hash = "sha256:98812844c34262def980bdf60923a875cd43428a8375b6fd53bd2cd800eccf0b"},
{file = "pyobjc_framework_Quartz-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1139bc6874c0f8b58f0b8602015e0994198bc506a6bcec1071208de32b55ed26"},
{file = "pyobjc_framework_Quartz-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ef18f5a16511ded65980bf4f5983ea5d35c88224dbad1b3112abd29c60413ea"},
{file = "pyobjc_framework_Quartz-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b41eec8d4b10c7c7e011e2f9051367f5499ef315ba52dfbae573c3a2e05469c"},
{file = "pyobjc_framework_Quartz-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c65456ed045dfe1711d0298734e5a3ad670f8c770f7eb3b19979256c388bdd2"},
@ -2398,16 +2421,16 @@ pytz = [
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
]
pywin32 = [
{file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"},
{file = "pywin32-300-cp35-cp35m-win_amd64.whl", hash = "sha256:350c5644775736351b77ba68da09a39c760d75d2467ecec37bd3c36a94fbed64"},
{file = "pywin32-300-cp36-cp36m-win32.whl", hash = "sha256:a3b4c48c852d4107e8a8ec980b76c94ce596ea66d60f7a697582ea9dce7e0db7"},
{file = "pywin32-300-cp36-cp36m-win_amd64.whl", hash = "sha256:27a30b887afbf05a9cbb05e3ffd43104a9b71ce292f64a635389dbad0ed1cd85"},
{file = "pywin32-300-cp37-cp37m-win32.whl", hash = "sha256:d7e8c7efc221f10d6400c19c32a031add1c4a58733298c09216f57b4fde110dc"},
{file = "pywin32-300-cp37-cp37m-win_amd64.whl", hash = "sha256:8151e4d7a19262d6694162d6da85d99a16f8b908949797fd99c83a0bfaf5807d"},
{file = "pywin32-300-cp38-cp38-win32.whl", hash = "sha256:fbb3b1b0fbd0b4fc2a3d1d81fe0783e30062c1abed1d17c32b7879d55858cfae"},
{file = "pywin32-300-cp38-cp38-win_amd64.whl", hash = "sha256:60a8fa361091b2eea27f15718f8eb7f9297e8d51b54dbc4f55f3d238093d5190"},
{file = "pywin32-300-cp39-cp39-win32.whl", hash = "sha256:638b68eea5cfc8def537e43e9554747f8dee786b090e47ead94bfdafdb0f2f50"},
{file = "pywin32-300-cp39-cp39-win_amd64.whl", hash = "sha256:b1609ce9bd5c411b81f941b246d683d6508992093203d4eb7f278f4ed1085c3f"},
{file = "pywin32-301-cp35-cp35m-win32.whl", hash = "sha256:93367c96e3a76dfe5003d8291ae16454ca7d84bb24d721e0b74a07610b7be4a7"},
{file = "pywin32-301-cp35-cp35m-win_amd64.whl", hash = "sha256:9635df6998a70282bd36e7ac2a5cef9ead1627b0a63b17c731312c7a0daebb72"},
{file = "pywin32-301-cp36-cp36m-win32.whl", hash = "sha256:c866f04a182a8cb9b7855de065113bbd2e40524f570db73ef1ee99ff0a5cc2f0"},
{file = "pywin32-301-cp36-cp36m-win_amd64.whl", hash = "sha256:dafa18e95bf2a92f298fe9c582b0e205aca45c55f989937c52c454ce65b93c78"},
{file = "pywin32-301-cp37-cp37m-win32.whl", hash = "sha256:98f62a3f60aa64894a290fb7494bfa0bfa0a199e9e052e1ac293b2ad3cd2818b"},
{file = "pywin32-301-cp37-cp37m-win_amd64.whl", hash = "sha256:fb3b4933e0382ba49305cc6cd3fb18525df7fd96aa434de19ce0878133bf8e4a"},
{file = "pywin32-301-cp38-cp38-win32.whl", hash = "sha256:88981dd3cfb07432625b180f49bf4e179fb8cbb5704cd512e38dd63636af7a17"},
{file = "pywin32-301-cp38-cp38-win_amd64.whl", hash = "sha256:8c9d33968aa7fcddf44e47750e18f3d034c3e443a707688a008a2e52bbef7e96"},
{file = "pywin32-301-cp39-cp39-win32.whl", hash = "sha256:595d397df65f1b2e0beaca63a883ae6d8b6df1cdea85c16ae85f6d2e648133fe"},
{file = "pywin32-301-cp39-cp39-win_amd64.whl", hash = "sha256:87604a4087434cd814ad8973bd47d6524bd1fa9e971ce428e76b62a5e0860fdf"},
]
pywin32-ctypes = [
{file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"},

View file

@ -55,7 +55,7 @@ speedcopy = "^2.1"
six = "^1.15"
semver = "^2.13.0" # for version resolution
wsrpc_aiohttp = "^3.1.1" # websocket server
pywin32 = { version = "300", markers = "sys_platform == 'win32'" }
pywin32 = { version = "301", markers = "sys_platform == 'win32'" }
jinxed = [
{ version = "^1.0.1", markers = "sys_platform == 'darwin'" },
{ version = "^1.0.1", markers = "sys_platform == 'linux'" }