From 7ea15624d3a27f2441751b463f7ef50c3d3c86bd Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:23:47 +0200 Subject: [PATCH 01/79] doc!: update cuesubmit example config file with new jobs syntax + help section --- cuesubmit/cuesubmit_config.example.yaml | 127 +++++++++++++++++++++++- 1 file changed, 123 insertions(+), 4 deletions(-) diff --git a/cuesubmit/cuesubmit_config.example.yaml b/cuesubmit/cuesubmit_config.example.yaml index 0a89a9f39..90d3d123b 100644 --- a/cuesubmit/cuesubmit_config.example.yaml +++ b/cuesubmit/cuesubmit_config.example.yaml @@ -5,7 +5,126 @@ UI_NAME : "OPENCUESUBMIT" SUBMIT_APP_WINDOW_TITLE : "OpenCue Submit" -MAYA_RENDER_CMD : "Render" -NUKE_RENDER_CMD : "nuke" -BLENDER_RENDER_CMD : "blender" -FRAME_TOKEN : "#IFRAME#" + +RENDER_CMDS: + Shell: + command: "" + options: + "{Command to run}": "\n" + + Maya: + command: "Render" + options: + "-r {Renderer}": + - file + - default + - hw2 + - sw + - arnold + "-s {Start Frame}": "#FRAME_START#" + "-e {End Frame}": "#FRAME_END#" + "{!mayaFile*}": + - Maya Ascii file (*.ma) + - Maya Binary file (*.mb) + - Maya file (*.ma *.mb) + + Blender: + command: "blender" + options: + "--background~": "" + "-noaudio~": "" + "{!file*}": + - Blender file (*.blend) + "-s {Start Frame}": "#FRAME_START#" + "-e {End Frame}": "#FRAME_END#" + "-o {Output Path (Optional)*}": "//render_" + "-F {Output Format}": ['', 'AVIJPEG', 'AVIRAW', 'BMP', 'CINEON', 'DPX', 'EXR', 'HDR', 'IRIS', 'IRIZ', + 'JP2', 'JPEG', 'MPEG', 'MULTILAYER', 'PNG', 'RAWTGA', 'TGA', 'TIFF'] + + Nuke: + command: "nuke" + options: + "-X {!Write Nodes}": "" + "-F {Frame Range}": "#FRAME_START#-#FRAME_END#" + "-x {!Nuke File}": + - Nuke Script File (*.nk) + + Isolated Job Example: + config_file: "$MAYA_JOB_CONFIG_FILE" + + +Help: > + RENDER_CMDS section describes custom job types that will appear in the UI + There are 2 ways to declare a job: + - directly in the list + - from a separate config file (yaml) + You can use environment variables to define paths + + 1) To configure a job directly: + Command name: + command: "path/to/executable" + options: + "-strFlag": "default value" + "-strFlagB {Nice Name}": "default value" + "-boolFlag": false + "-intFlag": 10 + # Creates a slider from 0 to 999 + "-intRange": [0, 5, 3] + #[min, max, default] + "-floatRange": [0, 1, 0.5, 2] + #[min, max, default, float_precision] + "-choiceList": + -choiceA + -choiceB + "-browsableFolder {Output Folder/}": "" + "-anyBrowsableFile {Any File*}": "" + "-filteredBrowsableFile {Maya File*}": + - Maya Ascii file (*.ma) + - Maya Binary file (*.mb) + - Maya file (*.ma *.mb) + "{No flag argument}": "" + "{!Mandatory argument}": "" + "-hiddenFlag~": "" + + Note: + - arguments order is respected + - flags can have double dash (--background) + - Syntax: + + "-flagName" + command uses `-flagName` + UI displays `-flagName` + + "-flagName {Nice Name}" + command uses `-flagName` + UI displays `Nice Name` + + "{Nice Name}" + command uses blank space (no flag) + UI displays `Nice Name` + + "-flagName~" + command uses '-flagName' + the widget is hidden + + "-f {Frame}": "#IFRAME#" + command uses '-f #IFRAME#' + the widget is hidden (with any opencue token) + + "{Nice Name}": "\n" + Creates a multiline widget + + To make string browsable, use: + "{Nice Name/}" for folders + "{Nice Name*}" for files + + To make an option mandatory, use: + "{!Nice Name}" + UI will make it red if empty + + 2) To load a command from another config_file: + Command Name: + config_file: "path/to/command/config.yaml" + + Note: + see cuesubmit_isolated_job_config.example.yaml \ No newline at end of file From 14a0385d8f129703d58fa1b471df40fab0dafba8 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:24:37 +0200 Subject: [PATCH 02/79] doc!: add a cuesubmit isolated example config file --- .../cuesubmit_isolated_job_config.example.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 cuesubmit/cuesubmit_isolated_job_config.example.yaml diff --git a/cuesubmit/cuesubmit_isolated_job_config.example.yaml b/cuesubmit/cuesubmit_isolated_job_config.example.yaml new file mode 100644 index 000000000..394a74c02 --- /dev/null +++ b/cuesubmit/cuesubmit_isolated_job_config.example.yaml @@ -0,0 +1,16 @@ +#Isolated Maya command example: +command: "Render" +options: + "-cam {!camera}": "persp" + "-s {startFrame}": "#FRAME_START#" + "-e {endFrame}": "#FRAME_END#" + "-log {logLevel}": [0, 5, 3] + "-renderer {engine}": + - arnold + - default + - hw2 + - sw + "{!mayaFile*}": + - Maya Ascii file (*.ma) + - Maya Binary file (*.mb) + - Maya file (*.ma *.mb) \ No newline at end of file From d761fac744f7dfddc0912c3e9722686f3825808d Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:25:25 +0200 Subject: [PATCH 03/79] feat: add `notEmptyString` validator --- cuesubmit/cuesubmit/Validators.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cuesubmit/cuesubmit/Validators.py b/cuesubmit/cuesubmit/Validators.py index 540f92e21..b4a1a13a8 100644 --- a/cuesubmit/cuesubmit/Validators.py +++ b/cuesubmit/cuesubmit/Validators.py @@ -70,3 +70,8 @@ def moreThan3Chars(value): if len(value) >= 3: return True return False +def notEmptyString(value): + """String must contain at least 1 character.""" + if len(value) == 0: + return False + return True From 72adc3d79397f22e4afbbd976b74f3aafb528167 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:34:29 +0200 Subject: [PATCH 04/79] feat: extract yaml loading to a function and add one to expand any sub `config_file` + error handling --- cuesubmit/cuesubmit/Config.py | 56 ++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/cuesubmit/cuesubmit/Config.py b/cuesubmit/cuesubmit/Config.py index 3bfb443a7..d2906d9a2 100644 --- a/cuesubmit/cuesubmit/Config.py +++ b/cuesubmit/cuesubmit/Config.py @@ -35,19 +35,59 @@ def getConfigValues(): """Reads the config file from disk and returns the values it defines.""" - configData = {} configFile = os.environ.get(CONFIG_FILE_ENV_VAR) if not configFile: configFile = os.path.join(opencue.config.config_base_directory(), 'cuesubmit.yaml') - if os.path.exists(configFile): - with open(configFile, 'r', encoding='utf-8') as data: - try: - configData = yaml.load(data, Loader=yaml.SafeLoader) - except yaml.YAMLError: - raise CuesubmitConfigError("Could not load yaml file: {}. Please check its " - "formatting".format(configFile)) + configData = _loadYamlFile(yaml_file=configFile) + if 'RENDER_CMDS' in configData: + # look for any sub-config files and load them + configData['RENDER_CMDS'] = _expandRenderConfigValues(configData['RENDER_CMDS']) return configData +def _loadYamlFile(yaml_file): + """ Load config yaml as dict + :param yaml_file: path to a config.yaml file (path can be an env var) + :type yaml_file: str + :returns: yaml content + :rtype: dict + """ + _yaml_file = os.path.expandvars(yaml_file) + if not os.path.exists(_yaml_file): + raise FileExistsError(f'{_yaml_file=} not found') + config_data = {} + with open(_yaml_file, 'r') as data: + try: + config_data = yaml.load(data, Loader=yaml.SafeLoader) + except yaml.YAMLError: + raise CuesubmitConfigError("Could not load yaml file: {}. Please check its " + "formatting".format(_yaml_file)) + return config_data + + +def _expandRenderConfigValues(RENDER_CMDS): + """ Looks through each render command and loads their 'config_file' if any + If 'config_file' is set but does not exist, replace its content with error for proper feedback + + :param RENDER_CMDS: all render commands from the cuesubmit_config.yaml file + :type RENDER_CMDS: dict + :returns: Updated RENDER_CMDS + :rtype: dict + """ + for job_type, _options in RENDER_CMDS.items(): + _sub_config_file = _options.get('config_file') + if not _sub_config_file: + continue + try: + RENDER_CMDS[job_type] = _loadYamlFile(yaml_file=_sub_config_file) + except FileExistsError as error: + RENDER_CMDS[job_type] = { + 'command': 'error', + 'options': { + '{ERROR}': error} + } + return RENDER_CMDS + + class CuesubmitConfigError(Exception): """Thrown when an error occurs reading the config file.""" From 959613dec1a4e0b14c50cae04c809737b86ca195 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:35:55 +0200 Subject: [PATCH 05/79] feat: load RENDER_CMDS in Constants --- cuesubmit/cuesubmit/Constants.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cuesubmit/cuesubmit/Constants.py b/cuesubmit/cuesubmit/Constants.py index 89bbbea51..aee7a2b8b 100644 --- a/cuesubmit/cuesubmit/Constants.py +++ b/cuesubmit/cuesubmit/Constants.py @@ -36,6 +36,8 @@ MAYA_RENDER_CMD = config.get('MAYA_RENDER_CMD', 'Render') NUKE_RENDER_CMD = config.get('NUKE_RENDER_CMD', 'nuke') BLENDER_RENDER_CMD = config.get('BLENDER_RENDER_CMD', 'blender') +RENDER_CMDS = config.get('RENDER_CMDS', {}) + FRAME_TOKEN = config.get('FRAME_TOKEN', '#IFRAME#') FRAME_START_TOKEN = config.get('FRAME_START', '#FRAME_START#') FRAME_END_TOKEN = config.get('FRAME_END', '#FRAME_END#') @@ -62,7 +64,6 @@ NUKE_FILE_FILTERS = ['Nuke script file (*.nk)'] BLENDER_FILE_FILTERS = ['Blender file (*.blend)'] - BLENDER_FORMATS = ['', 'AVIJPEG', 'AVIRAW', 'BMP', 'CINEON', 'DPX', 'EXR', 'HDR', 'IRIS', 'IRIZ', 'JP2', 'JPEG', 'MPEG', 'MULTILAYER', 'PNG', 'RAWTGA', 'TGA', 'TIFF'] BLENDER_OUTPUT_OPTIONS_URL = \ From f26d5ca82c594351015ce9a9ffc7cc550ca31ddd Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:39:16 +0200 Subject: [PATCH 06/79] feat: add regex to get opencue tokens --- cuesubmit/cuesubmit/Constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cuesubmit/cuesubmit/Constants.py b/cuesubmit/cuesubmit/Constants.py index aee7a2b8b..be7699669 100644 --- a/cuesubmit/cuesubmit/Constants.py +++ b/cuesubmit/cuesubmit/Constants.py @@ -69,6 +69,8 @@ BLENDER_OUTPUT_OPTIONS_URL = \ 'https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html#render-options' +REGEX_CUETOKEN = r'^#.*#$' #FRAME_START# + DIR_PATH = os.path.dirname(__file__) # Dropdown label to specify the default Facility, i.e. let Cuebot decide. From 195091ffc17360cb6c415c4651409917b4fb88c3 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Tue, 28 Mar 2023 21:39:59 +0200 Subject: [PATCH 07/79] feat: add regex to parse options from the cuesubmit config file --- cuesubmit/cuesubmit/Constants.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cuesubmit/cuesubmit/Constants.py b/cuesubmit/cuesubmit/Constants.py index be7699669..2f8f5d52f 100644 --- a/cuesubmit/cuesubmit/Constants.py +++ b/cuesubmit/cuesubmit/Constants.py @@ -70,6 +70,14 @@ 'https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html#render-options' REGEX_CUETOKEN = r'^#.*#$' #FRAME_START# +REGEX_COMMAND_OPTIONS = (r'(?P-+\w*)?' # -optionFlag + r'(?P\~)?' # -hiddenFlag~ + r'\s?' + r'({' + r'(?P\!)?' # {!Mandatory argument} + r'(?P